夜雨聆风学习资料网

ARTICLE · 1160668

Python 处理 Word 文档,别再死磕 python-docx 了,Spire.Doc 了解一下

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}}

下面还有一个动态表格:

产品
数量
金额
A
10
1000
B
20
2000

最后要求:

  • 批量生成 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 自动化这块,确实值得放进工具箱里。

别等模板改到第十版,再去重构。

相关学习资料