恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

python-docx实战:用Python实现Word文档自动化处理与批量生成

  • 首页
  • 资讯中心
  • /
  • python-docx实战:用Python实现Word文档自动化处理与批量生成

相关资讯

具身人工智能落地指南:技术原理、场景与数据基建 2026/10/14 5:18:04
矿井目标检测数据集:地下空间特异性与安全合规性标注实践 2026/10/14 5:18:04
微信小程序云开发超市库存管理系统源码解析与二次开发指南 2026/10/14 5:13:03

最新资讯

微信小程序知识付费闭环源码:支付→分润→会员→复购全链路实现
SA-SSD点云检测网络搭建全解析:从辅助任务耦合到维度对齐实战
ResNet50单模型实现Kaggle猫狗分类Top 7.8%实战
猫狗分类实战:三阶段渐进式迁移学习精要
MyBatis进阶技巧:简化代码提升开发效率
2026年最新--区块链行业产品经理面试题库(100题)

今日推荐

IBM Verify Identity Access 修复 22 个漏洞:两个 9.8 严重 RCE 无需认证
小区物业管理系统
小型超市仓库管理系统

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

python-docx实战:用Python实现Word文档自动化处理与批量生成

发布时间:2026/10/14 5:18:04
python-docx实战:用Python实现Word文档自动化处理与批量生成 每天处理一摞合同、几十份成绩单、周报月报还要保证格式统一手动复制粘贴迟早会把人逼疯。做办公自动化的时候我最先想到的就是python-docx。它不像VBA那样绑死Windows和Office也不用学一堆UI宏录制用Python就能完成Word文档的创建、编辑、样式控制、表格填充、批量生成特别是那些“同一个模板换几百个名字”的场景用它再合适不过。适合谁用经常跟Word打交道的开发、测试、运营、行政或者想优化办公流程的Python使用者都能从这篇里拿到能直接抄的代码。这篇文章不会只贴几个API我会把从环境准备、基础对象模型、模板替换、批量生成到页眉页脚、常见坑点、服务化扩展整条链路都拆开讲。你会看到我在真实项目里踩过的坑比如跨Run替换的诡异问题、中文字体设置不生效、表格列宽怎么调都不动等等。每个问题都附了解决思路和代码你可以直接拿去用。1. 为什么选择python-docx做Word文档自动处理1.1 手动处理Word文档的痛点先说一个真实的例子某公司行政每周要生成几十份供应商对账函内容结构完全一样就是公司名、合同编号、金额、日期不同。最早是手工复制上一周的文件再改结果每隔几周就有人把公司名填错或者忘记刷新日期。后来改成VBA宏虽然能用但同事电脑上宏被安全策略拦了几次不同Office版本行为还不一样维护起来非常心累。这类任务的核心问题在于文档本身是结构化的但人力处理时总会因为疲劳、复制错位导致低级错误。如果能让程序读取数据源再按模板自动生成就可以同时解决效率、准确率、可追溯三个问题。python-docx就是干这个的它让我用几十行代码就替换掉了一下午的手工劳动而且生成结果稳定到可以放心发出去。1.2 主流方案横向对比Word自动化方案不止python-docx一个但每个方案都有明显的边界。VBA宏依赖本机安装Office宏安全策略和版本兼容性很折磨人win32com其实是调用Windows的COM接口功能强大但只能在Windows上用部署环境一旦换成Linux就全线崩溃docxtpl这类基于模板引擎的方案写起来快可一旦需要精细控制XML细节就会受限。python-docx最大的优势是跨平台Windows、Linux、macOS都能跑底层只依赖lxml解析Office Open XML不要求装Office。它提供了一套相对上层的API既能像写作文档一样从头构建也能打开现有docx做修改还允许通过XML操作补足一些特殊需求。下面这个表是我在实际选型时的心得。方案跨平台依赖Office控制粒度推荐场景VBA宏否是中在单个Excel/Word内部复杂交互win32com否是高已锁定Windows环境的遗留系统docxtpl是否中高纯模板替换快速出活python-docx是否高创建、修改、批量生成、样式控制我当时选python-docx还有一个原因它可以和pandas、openpyxl、requests这类库放在同一个项目里。数据从Excel读取后直接变Word报表不需要通过中间格式倒手。1.3 安装与环境准备安装没什么幺蛾子直接pip安装即可。pip install python-docx建议创建一个虚拟环境别直接装到系统级Python里不然以后项目依赖打架会很难受。安装完成后在Python交互环境里验证一下版本。import docx print(docx.__version__)安装包内部会带一个默认模板很多初始化设置都依赖它。只要能看到版本号说明lxml和Python环境的配合没有问题。这里特别提醒一句python-docx只支持.docx后缀的新版Word文档遇到.doc老格式会直接报错这个坑我会在第6章单独展开。2. 核心对象模型先看懂docx的内部结构2.1 Document、Paragraph、Run三者的关系想用好python-docx先得弄懂它的三层结构。Document代表整个Word文档Paragraph代表一个段落Run则是一个段落内格式完全相同的文本片段。你可以把Document想成一张纸Paragraph是这张纸上的每一行字Run则是某一行里被画成红色、加粗、或者换过字体的那一小段。为什么同一个段落里会有多个Run因为Word的底层XML就是按格式片段存储文本的。你在Word里输入一句话期间切换过字体、颜色、加粗它就可能被拆成好几个Run。这个特性在查找替换时特别重要后面我会展示怎么解决“文本被拆在多个Run里导致替换失败”的问题。读取文档时最常见的操作就是遍历所有段落和Runfrom docx import Document doc Document(example.docx) for para in doc.paragraphs: print(段落文本, para.text) for run in para.runs: print(片段, run.text, 加粗, run.bold)如果你只需要拿到纯文本直接用para.text就行。但如果你想精确改动某一段文字的样式就必须定位到具体的Run。2.2 表格、节与样式都藏在哪很多人会直觉认为表格也属于paragraphs其实不是。docx的结构里正文是bodybody下面可以并行存在段落和表格两类块级元素。python-docx的 Document.paragraphs 只返回独立的段落Document.tables 才返回页面上的表格。如果文档里有一个表格前后夹着文字你要查找某个关键词必须同时遍历paragraphs和tables不然就会漏数据。Section表示节Word里通过分节符划分不同页面设置区域。一个文档可以有很多个Section每个Section有独立的纸张大小、页边距、页眉页脚。调用doc.sections[0]只能拿到第一节多分节文档必须遍历处理这个细节在批量生成周报时特别容易翻车。Style是样式对象文档里内置了Normal、Heading 1、Title这些样式。你可以修改内置样式也可以创建自定义样式。样式的作用范围是段落或Run设置后可以减少大量重复的格式代码。2.3 读取已有文档时的遍历套路读文档之前先想清楚你要做什么是全文替换关键字段还是提取所有文本做分析还是只改某个位置的图片目标不同遍历的写法也不同。下面这个函数可以同时遍历段落和表格并把表格里的文字也搜索出来def iter_block_items(doc): from docx.document import Document as _Doc from docx.oxml.table import CT_Tbl from docx.oxml.text.paragraph import CT_P from docx.table import Table from docx.text.paragraph import Paragraph parent_elm doc.element.body for child in parent_elm.iterchildren(): if isinstance(child, CT_P): yield Paragraph(child, doc) elif isinstance(child, CT_Tbl): yield Table(child, doc)这个函数的好处是严格按照body元素的顺序返回段落和表格你调试时能清楚看到文档结构。很多项目里的诡异问题比如“文字明明在文档里document.paragraphs却找不到”基本都是因为目标文字藏在表格单元格里。单元格里的段落需要通过cell.paragraphs访问下一章我会展示递归处理方案。3. 从零生成一份带样式的报告3.1 设置全局默认字体和段落格式新建文档后第一步不要急着写内容先把全局样式定好。直接用默认模板生成的文档正文样式是Calibri字体对中文很不友好。很多人在Word里手动打开没问题是因为Word自动做了字体回退但你把生成的docx发给别人可能看到的是一堆方块。正确做法是修改Normal样式同时设置西文字体和中文字体from docx import Document from docx.shared import Pt, RGBColor from docx.oxml.ns import qn doc Document() style doc.styles[Normal] style.font.name Times New Roman style.font.size Pt(12) style.element.rPr.rFonts.set(qn(w:eastAsia), 宋体)那行 style.element.rPr.rFonts.set(qn(w:eastAsia), 宋体) 是关键。Word的字体配置分成ascii字体和eastAsia字体两套只设置font.name只能改西文字体中文还得通过XML设置eastAsia属性。很多教程没提这步照着写完之后中文没变大概率就是漏了这里。段落格式同样可以统一设置比如首行缩进、行距、段后间距pf style.paragraph_format pf.space_after Pt(6) pf.line_spacing 1.5 pf.first_line_indent Pt(24)设置完这些后续创建的段落都会继承省去大量重复操作。3.2 插入标题、正文、列表与分页python-docx提供了一组快速插入方法add_heading会自动套用标题样式add_paragraph会使用Normal样式需要列表时直接以“1.”这类字符串开头就行。更标准的方式是使用List Number和List Bullet样式doc.add_heading(一、项目概述, level1) doc.add_paragraph(这里写正文内容自动使用Normal样式。) doc.add_paragraph(第一项要点, styleList Bullet) doc.add_paragraph(第二项要点, styleList Bullet) doc.add_paragraph(第一条操作步骤, styleList Number) doc.add_page_break()add_page_break会在当前光标位置插入一个分页符。报告类文档常用这个方式让每个新章节从新页面开始。对齐方式和行距不一定都要靠样式继承也可以在单个段落上直接设置from docx.enum.text import WD_ALIGN_PARAGRAPH para doc.add_paragraph() para.alignment WD_ALIGN_PARAGRAPH.CENTER run para.add_run(居中显示的标题信息) run.bold True run.font.size Pt(14)这里有个小技巧add_paragraph会返回一个Paragraph对象add_run会返回一个Run对象后续想修改哪个部分就通过这两个对象操作不用回过来重新查找。3.3 图片插入与尺寸控制插入图片的核心是add_picture你想要控制宽高时直接传入Cm或Inches对象。Emu是Word底层的最小长度单位python-docx的shared模块帮我们封装好了换算。from docx.shared import Cm doc.add_picture(chart.png, widthCm(14))图片宽度设成14厘米时高度会按原图比例自动缩放。如果担心图片比例变形可以先用PIL读取原图尺寸再按比例计算目标高度。图片居中是个容易忽略的细节。add_picture本身没有对齐参数它会在当前段落内插入一个InlineShape。你需要先把光标所在的段落设置为居中再插入图片或者插完后设置这个段落的对齐方式last_paragraph doc.paragraphs[-1] last_paragraph.alignment WD_ALIGN_PARAGRAPH.CENTER一次生成多张图片时我习惯把“插入图片并居中”封装成函数避免代码里到处都是段落处理逻辑。3.4 表格的创建、填充与格式化创建表格用doc.add_table然后指定行数、列数。样式可以先设置为Table Grid不然默认表格没有任何边框打印出来跟没有表格一样。table doc.add_table(rows3, cols3) table.style Table Grid table.cell(0, 0).text 项目 table.cell(0, 1).text 数量 table.cell(0, 2).text 备注批量填充数据时用循环比一行行写更可靠data [ [服务器, 3, 生产环境], [存储设备, 2, 备份使用], ] for row_idx, row_data in enumerate(data, start1): for col_idx, value in enumerate(row_data): table.cell(row_idx, col_idx).text value合并单元格也是常见需求比如表头跨两列。使用cell.merge方法merged table.cell(0, 0).merge(table.cell(0, 1)) merged.text 合并后的标题格式化单元格内容时先通过cell.paragraphs[0]拿到段落再加Run设置字体。cell.text设置后再想改单元格内某段文字的颜色就需要这样操作cell table.cell(1, 0) para cell.paragraphs[0] run para.add_run(强调内容) run.bold True如果你直接设置cell.text xxx你会发现无法对里面的某个词设置样式因为cell.text一步到位会重新生成段落和Run。需要精细排版时用add_run更顺手。4. 模板替换与批量生成的实战经验4.1 占位符设计规范批量生成文档最常用的方式不是从头编码而是准备一个Word模板里面放好占位符程序负责把占位符替换成真实数据。占位符长得太普通容易误伤员工名比如你搜“张三”替换结果正文里本来就有个“张三丰”。所以我的习惯是使用双花括号包裹比如{{姓名}}、{{合同编号}}。模板中的占位符必须保证文本唯一并且不要跨表格单元格使用。同一个变量可能在多个位置出现可以接受。但一个占位符绝对不能被人为断成两段否则替换逻辑会很复杂。另外模板里的占位符尽量设置成跟正文一致的样式不要为了醒目给它标红。因为很多替换方案是重建Run如果你让占位符有特殊格式替换后的真实文字可能会继承一个多余的空Run导致Word里出现莫名其妙的残留格式。4.2 解决跨Run替换的核心问题前面提到一个段落可能被Word拆成多个Run。比如“{{姓名}}”这个占位符可能被拆成“{{”和“姓名}}”两段。如果只遍历每个Run做字符串替换你会替换不完整。最稳妥的办法是把整个段落的文本拼接一次完成替换后清空原Run再创建一个新的Run写入结果。下面是我一直在用的替换函数经过很多文档验证import re from docx import Document def replace_in_paragraph(paragraph, placeholders): full_text .join(run.text for run in paragraph.runs) new_text full_text for key, value in placeholders.items(): new_text new_text.replace(key, value) if new_text full_text: return for run in paragraph.runs: run.text if new_text: paragraph.add_run(new_text)这个方案会丢失段落内原有的多种Run格式合并成一个普通格式在大多数模板替换场景里可以接受。如果你要保留富文本样式就得做基于Run长度的映射复杂度会高很多。我的经验是模板占位符尽量单独占一个段落替换后统一重新设置一遍字体最省心。4.3 表格与重复区域的占位符替换模板里经常有表格占位符位于单元格内。这时不能只遍历doc.paragraphs因为表格里的段落不属于paragraphs列表。必须遍历所有表格再递归访问表格内的单元格。def replace_in_table(table, placeholders): for row in table.rows: for cell in row.cells: for paragraph in cell.paragraphs: replace_in_paragraph(paragraph, placeholders) def replace_in_doc(doc, placeholders): for paragraph in doc.paragraphs: replace_in_paragraph(paragraph, placeholders) for table in doc.tables: replace_in_table(table, placeholders)如果表格里还有嵌套表格cell.tables可以继续递归。遇到这种复杂结构建议写一个完整的递归函数把body里所有块级元素都遍历一遍避免漏替换。重复区域的动态扩展是另一类需求比如工单记录条数不固定模板里只有一行示例数据需要根据数据量复制行。python-docx没有提供直接添加行的API但可以通过add_row加行再把新行的格式手工复制。最简单的方式是获取模板行的XML用深拷贝插入表格末尾from copy import deepcopy def add_row_like(table, template_row): row table.add_row() for i, cell in enumerate(template_row.cells): row.cells[i].text cell.text return row这个办法在通用场景下够用但如果模板行里包含合并单元格直接text复制会丢掉合并结构需要更深层的XML克隆。我建议模板尽量别用复杂合并动态表越简单越可靠。4.4 批量生成完整流程批量生成的核心是循环数据列表每循环一次加载一次模板替换后另存为新文件。这听起来简单实际操作时有两个要点一是模板文件要只读加载二是每个输入都显式保存并关闭避免句柄积累。from docx import Document from pathlib import Path template_path Path(template.docx) output_dir Path(output) output_dir.mkdir(exist_okTrue) records [ {姓名: 张三, 部门: 技术部, 合同编号: HT-001}, {姓名: 李四, 部门: 市场部, 合同编号: HT-002}, ] for idx, record in enumerate(records, start1): doc Document(template_path) replace_in_doc(doc, record) output_path output_dir / f合同_{idx}.docx doc.save(output_path) print(f已生成{output_path})如果数据量达到几百上千份建议在循环里增加一条保存后释放的逻辑。python-docx对象用完可以设置doc None让垃圾回收及时释放内存。实测中一次跑几千份文档时如果不做释放内存占用会缓慢上涨最后可能拖慢整个进程。生成完成后一定要抽查至少一份文件用Word打开看看模板里的分页符、表格样式、图片位置是否正常。自动化脚本不是跑通就结束输出文件要经得住人工检查才算合格。5. 页面设置、页眉页脚与章节控制5.1 纸张方向与页边距的正确设置有的报告需要纵向页面有的需要横向页面放宽表格。python-docx里通过Section对象控制。修改纸张方向时有个容易踩的细节仅修改orientation属性页面宽高不会自动互换需要把page_width和page_height也做对应调整。from docx.enum.section import WD_ORIENT section doc.sections[0] section.orientation WD_ORIENT.LANDSCAPE section.page_width Cm(29.7) section.page_height Cm(21.0)页边距直接设置四个方向即可section.top_margin Cm(2.5) section.bottom_margin Cm(2.5) section.left_margin Cm(3.0) section.right_margin Cm(2.5)如果你只是想要某几页是横向其他页是纵向就必须使用分节符而不是直接设置section。一个Section对应一个连续的页面空间所以多方向混排需要多个Section。5.2 页眉页脚和页码域的XML操作页眉页脚可以通过section.header和section.footer访问。默认情况下每个Section会继承前一节的页眉页脚所以当你只想让第一节有封面页眉第二节开始没有时需要单独设置。最常见的是在页脚插入“第 X 页共 Y 页”。python-docx没有直接提供页码域方法需要通过XML插入字段代码from docx.oxml.ns import qn from docx.oxml import OxmlElement def add_page_number(paragraph): run paragraph.add_run() fld_char1 OxmlElement(w:fldChar) fld_char1.set(qn(w:fldCharType), begin) instr_text OxmlElement(w:instrText) instr_text.set(qn(xml:space), preserve) instr_text.text PAGE fld_char2 OxmlElement(w:fldChar) fld_char2.set(qn(w:fldCharType), end) run._r.append(fld_char1) run._r.append(instr_text) run._r.append(fld_char2)插入完成后Word打开会自动计算页码。但有些查看器打开docx不会立即刷新域需要用户手动CtrlA再F9刷新。批量生成的文档如果只发电子版这个问题不大。页眉里放图片也是常用操作比如公司Logo。直接使用run.add_picture传路径即可header_para section.header.paragraphs[0] header_para.alignment WD_ALIGN_PARAGRAPH.CENTER header_para.add_run().add_picture(logo.png, heightCm(1.2))页眉中的图片和正文中图片的用法一致区别只是存放位置。注意页眉里的段落可能本来就有一个空Run直接用add_picture会追加在空Run后面一般不影响。5.3 多分节模板的注意事项现实中的模板经常被分成好几节比如封面节、正文节、附录节。这时最忌讳只处理doc.sections[0]。在多节文档里每个节的页边距、纸张、页眉页脚都可能不同。我在处理一个招标文件模板时遇到过这种问题程序只改了sections[0]的页脚结果只有封面页有页脚后面正文全都没有。后来改成统一遍历所有section批量设置问题立刻消失。还需要注意页眉页脚的“链接到前一节”属性。如果不想让后一节的页脚沿用前一节内容要关闭这个链接section.footer.is_linked_to_previous False这个属性在python-docx里的表现比较直接设为False后这一节的页脚就独立了。否则你改后一节页脚前一节也跟着变排查起来让人抓狂。6. 高频问题排查清单6.1 文件打不开或保存失败生成的文件打不开第一个怀疑对象是模板文件损坏。python-docx的保存本质是修改原docx的压缩包结构如果模板本身是WPS或其他Office软件生成的存在兼容性差异保存后可能无法被Word正常打开。解决办法是先检查模板用Word另存为纯docx再作为基线。如果是保存时报告PermissionError多是被别的进程占用。Windows上尤其常见脚本保存前不能打开同一个文件。用代码生成新文件时我习惯先保存到临时文件名保存成功后再用os.replace覆盖目标文件避免保存一半时进程崩溃产生损坏文件。文件数量多时这个习惯能救回不少数据。6.2 中文乱码与字体不生效中文乱码或依然显示Calibri核心原因是eastAsia字体没设置。前面3.1小节已经给出设置代码这里再强调一次不要只写style.font.name一定要写style.element.rPr.rFonts.set(qn(w:eastAsia), 宋体)。如果文档里某些段落还是不正常可能是因为那些段落没有继承Normal样式或者Run级别单独设置了字体。强制统一的方法是在每个Run上设置run.font.name Times New Roman run._element.rPr.rFonts.set(qn(w:eastAsia), 宋体)批量处理时我封装了一个set_run_font函数在每次创建Run后调用确保没有一个Run漏网。6.3 样式改了却不生效修改doc.styles[Normal].font.size后旧段落可能没反应。因为Word的样式应用策略是段落样式和Run样式层层覆盖Run上的直接格式优先于样式。python-docx新增段落时一般会有一个空Run如果你在这个Run上设置了局部格式后续再改样式就覆盖不了它。更稳妥的做法是尽量使用自定义命名样式。模板阶段就定义好“正文-小四”“标题-加粗”这些样式代码里只指定style不直接操作Run样式。这样后期想统一调整只改样式定义就行不会出现几十个文件里硬编码字体参数的惨状。6.4 表格列宽怎么都不听话python-docx里表格宽度由多个因素叠加决定表格宽度、单元格宽度、自动调整设置、网格列宽。最烦人的是table.autofit默认值为TrueWord打开时会对列宽重新自适应导致你设置的宽度失效。要固定列宽必须同时做三件事table.autofit False table.allow_autofit False for col in table.columns: col.width Cm(4) for row in table.rows: for cell in row.cells: cell.width Cm(4)看到没有列对象的width和单元格的width都要设置。因为docx的XML中cell宽度是存到每个单元格里的。只设columns不够只设cells也可能因为表格网格不一致而显示异常。还有一个隐藏因素Word的“自动调整”还受表格grid定义影响。如果模板表格已经存在并且grid有预定列宽你直接改cell.width有时不生效。这种情况可以尝试设置单元格的同名属性并用如下方式刷新cell._tc.tcPr.tcW.type dxa cell._tc.tcPr.tcW.w str(int(Cm(4).emu / 635 / 20))不过这属于偏底层的操作建议优先调整模板让模板表格尽量简单。6.5 旧版.doc文件怎么处理python-docx明确不支持.doc。.doc是二进制OLE格式.docx是XML压缩包两者完全不同。如果你输入的是.docDocument(old.doc)会报错或读取出来为空。处理办法有几种。最简单的是要求业务方先另存为.docx。如果文件很多可以用LibreOffice的命令行做批量转换soffice --headless --convert-to docx --outdir ./converted ./input.doc转换后还要人工检查排版因为.doc转.docx不是无损的尤其是复杂表格和文本框。如果只是读取文本用于数据提取也可以试试其他库但如果要做格式保留的自动化处理最好的路径还是让源文件从一开始就用新版Word格式。7. 从脚本到自动化服务的扩展方向7.1 与pandas联动的数据报表场景批量合同和通知是模板替换的典型场景另一类更常见的需求是把结构化数据变成一份可读性强的Word分析报告。最舒服的做法是pandas负责数据处理python-docx负责排版输出。import pandas as pd from docx import Document df pd.read_excel(sales.xlsx) doc Document() doc.add_heading(月度销售分析, level1) for _, row in df.iterrows(): doc.add_paragraph(f{row[区域]}销售额 {row[金额]}完成率 {row[完成率]}) table doc.add_table(rowsdf.shape[0] 1, colsdf.shape[1]) table.style Table Grid for col_idx, col_name in enumerate(df.columns): table.cell(0, col_idx).text str(col_name) for row_idx, row in df.iterrows(): for col_idx, value in enumerate(row): table.cell(row_idx 1, col_idx).text str(value) doc.save(report.docx)这里有一个取舍数据量大时表格可能跨页Word会自动分页但表格头不会自动重复。如果想每页都显示表头需要设置表格行属性为重复标题行这又要走XML操作。简单场景下我会把表格拆成不超过30行的多个子表可读性反而更好。7.2 封装成命令行小工具如果是给同事用最省事的方式是封装成命令行工具。用argparse接收模板路径、数据文件路径、输出目录避免让同事直接改Python代码。import argparse def main(): parser argparse.ArgumentParser(descriptionWord模板批量生成工具) parser.add_argument(--template, requiredTrue, help模板docx路径) parser.add_argument(--data, requiredTrue, help数据xlsx路径) parser.add_argument(--output, defaultoutput, help输出目录) args parser.parse_args() df pd.read_excel(args.data) os.makedirs(args.output, exist_okTrue) for idx, record in df.iterrows(): payload {col: str(record[col]) for col in df.columns} doc Document(args.template) replace_in_doc(doc, payload) doc.save(os.path.join(args.output, f文档_{idx 1}.docx)) if __name__ __main__: main()命令行工具的好处是容易接入其他系统。同事在桌面上跑一条命令就能出结果后续替换数据源、增加字段都不需要重新培训。7.3 定时任务与Web接口化如果每天固定时间要生成日报可以把脚本挂到定时任务里。最简单的方案是使用系统自带的cron或Windows任务计划程序。脚本本身要保持幂等也就是每次运行都从模板和源数据重新生成不要依赖上一次的运行状态。Web接口化是另一个方向。用Flask或FastAPI包一个HTTP接口前端上传模板和数据后端处理完返回下载链接。这个方案很吸引人但要注意并发安全python-docx不是为高并发设计的多个请求同时操作同一个模板文件会互相影响。我的做法是每次请求先把模板复制到临时目录在临时目录里处理处理完再把结果路径存入数据库。同时用文件锁或任务队列限制同一时间只处理一个生成任务。这样虽然牺牲了一点吞吐量但胜在稳定。如果只是内部工具用FastAPI做同步接口就够了。假设同时有几十个人使用再把任务改为异步队列后台逐条生成。核心逻辑不变换一层调度外壳即可。最后再分享一个实用习惯我在接手新文档模板时从来不会直接写代码。第一步永远是手工打开docx在Word里把所有常见的段落、表格、分节符、页眉页脚都看一遍再用python-docx写个小脚本把document.paragraphs和document.tables全部打出来。一边看结构一边对照XML思路后面写批量生成代码会顺利非常多。另外正式跑批量任务前先拿一条真实数据生成一份样板文档发给业务方确认格式。等对方说“可以”再全量跑能避免一次性生成几百份错模板的尴尬。自动化不是取代所有人工检查而是把人工从重复劳作中解放出来放在真正值得判断的地方。这个原则比任何库技巧都重要。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号