用 Python + python-docx 批量生成带表格样式的装修报价单 Word 文档(含合计公式)

装修公司每天要出十几份报价单,手工在 Word 里画表格、填单价、算合价、加合计,既慢又容易算错。本文用纯 Python(python-docx + openpyxl)把"Excel 报价源数据"一键转成格式统一、带合计行的 Word 文档,适合做报价系统的后端模板。

一、为什么不用直接复制 Excel

Excel 转到 Word 大多靠手工粘贴,丢格式、丢边框、合价列还经常算错。我们的目标:源数据在 Excel(设计/施工/主材分 sheet),脚本读出来,自动生成一份排版规范的 .docx,每个分项一行,末行自动算"工程总价"。

二、依赖与准备

bash 复制代码
pip install python-docx openpyxl

源 Excel 约定三列:项目 / 单价(元) / 工程量,另可选 单位。合价 = 单价 × 工程量,由脚本计算,避免手填出错。

三、核心代码

python 复制代码
from docx import Document
from docx.shared import Pt, RGBColor, Cm
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
import openpyxl

def read_items(path):
    wb = openpyxl.load_workbook(path)
    ws = wb.active
    items = []
    for row in ws.iter_rows(min_row=2, values_only=True):
        name, price, qty, unit = row[0], row[1], row[2], row[3] or '项'
        if name is None:
            continue
        items.append((name, float(price), float(qty), unit,
                      round(float(price) * float(qty), 2)))
    return items

def build_docx(items, out):
    doc = Document()
    # 标题
    h = doc.add_heading('装修工程报价单', level=0)
    h.alignment = WD_ALIGN_PARAGRAPH.CENTER

    table = doc.add_table(rows=1, cols=5)
    table.style = 'Light Grid Accent 1'
    table.alignment = WD_TABLE_ALIGNMENT.CENTER
    hdr = table.rows[0].cells
    for i, t in enumerate(['项目', '单价(元)', '工程量', '单位', '合价(元)']):
        hdr[i].text = t

    total = 0.0
    for name, price, qty, unit, sub in items:
        cells = table.add_row().cells
        cells[0].text = str(name)
        cells[1].text = f'{price:.2f}'
        cells[2].text = f'{qty:.2f}'
        cells[3].text = str(unit)
        cells[4].text = f'{sub:.2f}'
        total += sub

    # 合计行(加粗)
    sum_row = table.add_row().cells
    sum_row[0].text = '工程总价'
    sum_row[4].text = f'{total:.2f}'
    for c in sum_row:
        for p in c.paragraphs:
            for r in p.runs:
                r.font.bold = True

    # 数字列右对齐、字号统一
    for row in table.rows:
        for ci in (1, 2, 4):
            cell = row.cells[ci]
            for p in cell.paragraphs:
                p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
                for r in p.runs:
                    r.font.size = Pt(10)

    doc.save(out)
    print('saved', out, '| 总价', round(total, 2))

if __name__ == '__main__':
    items = read_items('quote.xlsx')
    build_docx(items, '报价单.docx')

四、三个容易踩的坑

  1. 中文路径报编码错误 :openpyxl/python-docx 本身是 Unicode 安全的,报错大多来自日志里手拼路径。统一用原始字符串 r'...' 或 pathlib.Path,别用 gbk 硬解码。
  2. 合计行被当成数据行 :iter_rows(min_row=2) 已经跳过表头,但若 Excel 末尾有空行,要用 if name is None: continue 过滤,否则会出现一行空单价把总价算崩。
  3. 表格样式不生效 :table.style 只接受 Word 内置样式名(如 Light Grid Accent 1),写错名字会静默失败、表格无边框。不确定的话用 doc.styles 打印可用名再选。

把这套逻辑封成接口,配合前端表单,就能让客户在线填完需求立马下载一份规范的报价单------这正是 maixuzi.cn 在线报价系统在后端做的事。更多装修数字化工具模板见 maixuzi.cn/resources/

相关推荐
1-1=02 小时前
Python PyCharm
开发语言·python·pycharm
梦影_2 小时前
Langchain简单快速上手教程(九)—— 核心组件之少样本提示
人工智能·python·自然语言处理·中间件·langchain
牛肉胡辣汤2 小时前
Blender + Three.js 开发讲解:从 .blend 到能转的产品页
开发语言·javascript·blender
惊讶的猫2 小时前
Spring AOP
java·开发语言
机械设计扫地僧2 小时前
用PYTHON工具对FAG INA CS 系列薄壁轴承进行初步选型筛选
python
ii_best2 小时前
按键精灵手机助手 v5.2.1 实测:inputText 逐字延时 + 调试面板多行复制,安卓脚本开发的两个输入痛点一次解决
android·开发语言·智能手机·自动化·ai编程·按键精灵
波力海苔夹心脆6752 小时前
C# StringBuilder 详解:字符串拼接为什么总说要用它?
开发语言·笔记·c#·.net·字符串·stringbuilder·入门教程
ZKNOW甄知科技2 小时前
燕千云迭代版本发布:智能Agent深入业务现场
运维·人工智能·低代码·机器学习·自然语言处理·自动化·aigc
Wang's Blog2 小时前
Java 项目实战: 交友项目 - 今日佳人:需求分析
java·开发语言·交友