用 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/

相关推荐
沐晓时光16 小时前
C语言入门,内存函数知识讲解
c语言·开发语言
用户9562562542920 小时前
跟做:Firecrawl 单页转 Markdown 再丢进沙箱总结
python·api
威哥爱编程20 小时前
模拟面试智能体开发实战 02:回答等半分钟,谁还愿意练?把服务端和流式输出搭起来
python·agent·harmonyos
威哥爱编程20 小时前
模拟面试智能体开发实战 01:面试挂了都不知道挂在哪?用 Python 给自己造一个随叫随到的 AI 面试官
python·agent·harmonyos
2601_9679801121 小时前
Python行情API量化 02:顺序拉 20 要 2 秒?并发批量把时间压到 0.5 秒
python·api·限流·并发·量化
伞伞悦读21 小时前
【第81期】特征缩放怎么选:标准化、MinMax 与 Robust 的原理、泄漏对照和完整实验
人工智能·python·深度学习·机器学习
新*21 小时前
从一段 WebSocket 代码聊开:bytes 不是 zlib、binaryType 决定一切,15MB 大消息的零拷贝优化
javascript·python·websocket·性能优化·blob·zlib·arraybuffer
David猪大卫1 天前
【C++修炼】map 和 set 的使用
c语言·开发语言·数据结构·c++·经验分享·笔记·学习
卷无止境1 天前
mathmodel-figure-templates 以及两个上手案例
后端·python
fengci.1 天前
CTF2MISC中等部分
开发语言·前端·学习