在日常办公中需要大量使用word的小伙伴们应该会发现,其实许多文档具有高度固定的结构:比如合同条款、报告框架、通知函等,变化的通常只是其中的业务数据或人员信息。当需要生成大量相似文件的时候,手动复制旧文件、查找替换、调整排版的方式,不仅耗时,还容易导致版本错乱、关键字段遗漏等问题。
今天我们来看看利用 Python 的 docxtpl 库实现文档模板化生成的方法。其核心思路是将排版结构与业务数据解耦,通过模板引擎实现数据注入,提供可复用、可维护的自动化方案。(跑通一次就可以无限复用!)
传统替换/手动操作 | 模板化生成 |
|---|---|
容易破坏格式,比如局部加粗、字体丢失 | 100% 继承模板原有样式、段落与表格结构 |
业务规则变更需逐个调整文件 | 仅需更新模板文件,代码逻辑保持稳定 |
依赖人工核对 | 可直接对接数据库、Excel、API 返回的 JSON |
非常适用于:批量合同/协议、周期性报告、标准化表单、证书/通知等。
docxtpl 与 Jinja2 语法docxtpl 基于 python-docx 与 Jinja2 模板引擎封装,允许在 Word 文档中直接使用模板语法。其核心工作原理如下:
{{ 变量名 }} 标记需替换的字段。render() 方法。.docx 文件。contract_template.docx)在 Word 中按标准合同排版,需动态替换的位置使用双大括号标记:
劳动合同甲方:{{ company_name }}乙方:{{ employee_name }}身份证号:{{ id_number }}一、合同期限本合同期限自 {{ start_date }} 起至 {{ end_date }} 止。二、岗位与薪酬乙方在 {{ department }} 担任 {{ position }},月薪资为 {{ salary }} 元。
💡 注意:模板中的占位符建议使用英文命名,避免与中文字体渲染冲突;排版完成后保存为
.docx格式。
import osfrom datetime import datetime, timedeltafrom docxtpl import DocxTemplatedef batch_generate_contracts(data_list: list[dict], template_path: str, output_dir: str):if not os.path.exists(template_path):raise FileNotFoundError(f"模板文件不存在: {template_path}")os.makedirs(output_dir, exist_ok=True)doc = DocxTemplate(template_path) # 模板只需加载一次for employee in data_list:# 计算结束日期(示例:固定3年)start = datetime.strptime(employee["start_date"], "%Y-%m-%d")end = start + timedelta(days=3*365)context = {"company_name": "XX科技有限公司","employee_name": employee["name"],"id_number": employee["id_number"],"start_date": employee["start_date"],"end_date": end.strftime("%Y-%m-%d"),"department": employee["department"],"position": employee["position"],"salary": f"{employee['salary']:,.0f}"}doc.render(context)filename = f"{employee['name']}_劳动合同.docx"doc.save(os.path.join(output_dir, filename))print(f"已生成: {filename}")if __name__ == "__main__":# 示例数据(实际可从数据库、CSV 或内部 API 获取)employees = [{"name": "张三", "id_number": "1111", "start_date": "2026-05-01", "department": "研发部", "position": "后端工程师", "salary": 15000},{"name": "李四", "id_number": "2222", "start_date": "2026-05-01", "department": "产品部", "position": "产品经理", "salary": 13000},{"name": "王五", "id_number": "3333", "start_date": "2026-05-01", "department": "设计部", "position": "UI设计师", "salary": 11000}]batch_generate_contracts(data_list=employees,template_path="contract_template.docx",output_dir="./output_contracts")
运行后,程序会读取模板,注入对应数据,并在 output_contracts 目录下生成排版一致、数据准确的合同文件。
若需在合同中附加项目履历或培训记录,可在 Word 表格中使用行循环语法:
项目名称 | 担任角色 |
|---|---|
|
|
⚠️ 注意:
{%tr %}必须包裹表格行级别,不可跨单元格拆分。渲染时会自动复制该行并填充数据。
根据岗位类型显示不同条款:
{% if position == "高级软件工程师" %}四、技术保密与竞业限制乙方在职期间及离职后两年内,不得参与与甲方核心业务存在直接竞争的项目。{% endif %}
InlineImage 类可动态插入公章、签名或图表。{{ header_var }},代码中传入对应键值即可生效。当文档生成从“重复劳动”沉淀为“标准流程”,我们真正优化的并非只是时间,而是人与事之间的关系。技术的意义从不在于替代思考,而在于腾出空间,让人重新成为工作的主导者~
更多python在办公自动化中的应用可以看这本