ARTICLE · 1160668
Python 处理 Word 文档,别再死磕 python-docx 了,Spire.Doc 了解一下
项目里有个需求:
每天晚上生成一批 Word 报告。
里面有客户信息、表格、图片、页眉页脚,还要根据模板替换内容。
刚开始接这个需求的时候,很多人第一反应都是:
Python 处理 Word,那肯定是 python-docx。
装一下:
pip install python-docx
然后开始写。
替换文字:
from docx import Document
doc = Document("template.docx")
for p in doc.paragraphs:
if"{{username}}"in p.text:
p.text = p.text.replace("{{username}}", "张三")
doc.save("result.docx")
看起来没问题。
直到模板复杂一点。
然后各种奇怪的问题开始出现。
比如:
表格里面的文字替换不了; 图片位置乱了; 原来的字体样式没了; 页眉页脚不好处理; Word 转 PDF 效果不一致。
这时候你会发现,python-docx 最大的问题不是不能用。
而是它更像一个“操作 Word 文档结构的工具”,不是一个完整的 Word 文档处理引擎。
很多时候,你只是想改一个字段,结果需要绕半天。
我之前处理这类需求,后面会直接换方案。
今天聊一下 Python 里的另一个选择:Spire.Doc。
python-docx 为什么容易卡住?
先说一个实际场景。
客户合同模板:
客户名称:{{customer_name}}
合同编号:{{contract_no}}
金额:{{amount}}
下面还有一个动态表格:
最后要求:
批量生成 500 份; 保留原 Word 样式; 自动转 PDF; 邮件发送。
如果只是替换几个段落,python-docx 没问题。
但 Word 内部结构其实比看起来复杂。
一个文字块:
{{customer_name}}
在 Word 里面可能不是一个完整字符串。
可能被拆成:
{{cus
tomer
_name}}
为什么?
因为 Word 会按照字体、样式、编辑历史拆 Run。
所以你代码里:
paragraph.text
看到的是完整内容。
但是实际修改时,样式信息已经丢了。
这也是很多人遇到的:
“我只是替换个变量,为什么整个段落字体变了?”
原因就在这里。
Spire.Doc 处理 Word 更接近文档引擎
Spire.Doc 是一个商业组件。
Python 版本可以直接处理 doc/docx。
安装:
pip install Spire.Doc
简单生成一个 Word:
from spire.doc import *
from spire.doc.common import *
document = Document()
section = document.AddSection()
paragraph = section.AddParagraph()
paragraph.AppendText("订单生成成功")
document.SaveToFile(
"order.docx",
FileFormat.Docx
)
document.Close()
这个例子没什么特别。
真正有价值的是它对已有 Word 模板的处理。
比如我们有一个模板:
订单编号:${order_id}
客户名称:${customer}
金额:${price}
代码:
from spire.doc import *
doc = Document()
doc.LoadFromFile("template.docx")
doc.Replace(
"${order_id}",
"NO20261001",
True,
True
)
doc.Replace(
"${customer}",
"上海某某科技有限公司",
True,
True
)
doc.Replace(
"${price}",
"26800",
True,
True
)
doc.SaveToFile(
"result.docx",
FileFormat.Docx
)
doc.Close()
这种模板替换方式,业务代码会舒服很多。
不用自己遍历:
paragraph; table; run; header。
表格处理,这个地方差距明显
Word 自动生成报告,表格基本跑不了。
比如订单明细:
from spire.doc import *
doc = Document()
doc.LoadFromFile("order_template.docx")
table = doc.Sections[0].Tables[0]
data = [
("MacBook", "2", "20000"),
("Mouse", "5", "500")
]
for i, row in enumerate(data):
new_row = table.AddRow()
new_row.Cells[0].Paragraphs[0].AppendText(row[0])
new_row.Cells[1].Paragraphs[0].AppendText(row[1])
new_row.Cells[2].Paragraphs[0].AppendText(row[2])
doc.SaveToFile(
"order_result.docx",
FileFormat.Docx
)
doc.Close()
业务系统里这种场景很多:
报价单; 检测报告; 财务报表; 生产记录。
如果天天手撸 Word XML,维护成本真的很高。
Word 转 PDF,这个需求特别常见
很多系统最后一步都是:
生成 Word。
然后:
转 PDF。
上传。
归档。
以前我见过不少项目这样搞:
先生成 docx。
调用 LibreOffice:
libreoffice --headless \
--convert-to pdf \
report.docx
能跑。
但是线上经常遇到:
Linux 环境字体缺失; 转换慢; 格式变化; 并发处理不稳定。
Spire.Doc 可以直接转:
from spire.doc import *
doc = Document()
doc.LoadFromFile("report.docx")
doc.SaveToFile(
"report.pdf",
FileFormat.PDF
)
doc.Close()
少了一层依赖。
部署简单很多。
图片、页眉页脚这些,python-docx 会比较痛苦
比如给报告加公司 Logo。
Spire.Doc:
from spire.doc import *
doc = Document()
doc.LoadFromFile("template.docx")
header = doc.Sections[0].HeadersFooters.Header
paragraph = header.AddParagraph()
picture = paragraph.AppendPicture(
"logo.png"
)
picture.Width = 120
picture.Height = 40
doc.SaveToFile(
"new.docx",
FileFormat.Docx
)
doc.Close()
这类东西在企业文档里非常常见。
合同。
通知。
检测报告。
都是模板 + 数据。
当然,Spire.Doc 也不是银弹
这个要说清楚。
如果只是:
生成一个简单 Word; 写几段文字; 插几张图片;
python-docx 足够。
没必要为了简单需求引入组件。
但是如果你的业务是:
每天批量生成大量 Word;
模板复杂;
需要保持格式;
需要 Word/PDF 双向转换;
需要处理表格、图片、页眉页脚;
那继续硬扛 python-docx,后面维护成本会越来越高。
我一般判断一个技术方案,不看它能不能做。
看的是:
半年以后改需求的时候,还能不能舒服地改。
Word 文档这类东西,最开始往往只是:
“帮我生成个文件。”
过几个月:
“能不能套客户模板?”
“能不能自动分页?”
“能不能加二维码?”
“能不能转 PDF?”
“能不能批量生成?”
需求一上来,简单脚本马上变成文档系统。
这时候选一个合适的文档处理引擎,比继续堆代码划算。
Spire.Doc 不一定适合所有场景。
但在 Python 做企业级 Word 自动化这块,确实值得放进工具箱里。
别等模板改到第十版,再去重构。