python-docx:Word文档生成与编辑

Python 办公自动化专题 · 用Python自动创建专业Word文档

专题:Python 自动化办公系统学习

关键词:Python, 自动化办公, python-docx, Word自动化, 文档生成, 段落格式, 表格, Python办公

一、python-docx概述

python-docx 是 Python 生态中最成熟的 Microsoft Word 文档操作库,它允许开发者在不安装 Microsoft Office 的情况下,通过编程方式创建和修改 .docx 格式文件。该库完全基于 Open XML 标准实现,提供了从简单文本操作到复杂文档布局控制的完整功能。无论是自动生成报表、批量制作合同,还是创建格式规范的学术论文,python-docx 都能胜任。

核心对象模型

python-docx 采用四层对象模型:Document(文档)是最顶层的容器对象,代表整个 Word 文件;Section(节)是文档的分区,每个节可以独立设置页面大小、边距和页眉页脚;Paragraph(段落)是文本的基本组织单元,包含段落级别的格式属性(对齐、缩进、间距等);Run(文本块)是段落内具有统一格式的连续文本片段,每个 Run 可以独立设置字体、大小、颜色、粗斜体等。理解这四个层级的关系是掌握 python-docx 的核心基础。

安装与导入

python-docx 通过 pip 一键安装,库本身是纯 Python 实现,无外部依赖,跨平台兼容性极好。安装完成后通过 import docx 或 from docx import Document 即可使用。

pip install python-docx
from docx import Document from docx.shared import Pt, Inches, Cm, Emu from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.enum.style import WD_STYLE_TYPE from docx.oxml.ns import qn # 验证安装 doc = Document() print("python-docx 安装成功,版本:", docx.__version__)

基础使用流程

使用 python-docx 的基本流程分为三步:创建 Document 对象 → 通过调用 add_ 系列方法添加内容 → 调用 save 方法保存文件。所有内容操作都在内存中进行,save 时才写入磁盘。

from docx import Document # 第一步:创建文档对象 doc = Document() # 第二步:添加内容 doc.add_heading('Python自动化办公', level=0) doc.add_paragraph('通过python-docx库可以轻松创建Word文档。') # 第三步:保存文件 doc.save('my_document.docx')

与 VBA 对比分析

python-docx 相比传统的 VBA 方案有显著优势:跨平台支持(Windows/macOS/Linux),无需安装 Office 软件,可与 pandas、matplotlib、reportlab 等 Python 库无缝集成,支持 CI/CD 自动化部署和版本控制。VBA 的优势在于与 Office 应用程序深度集成,可操作更多 Word 高级功能(如宏、ActiveX 控件、邮件合并等),但局限于 Windows 平台且需要完整的 Office 环境。对于大多数文档生成和自动化场景,python-docx 是比 VBA 更现代、更灵活的选择。

要点总结:python-docx 的核心是 Document → Section → Paragraph → Run 四层对象模型。安装简单(pip install python-docx),跨平台无依赖,适合服务器端和自动化场景。与 VBA 相比更适合现代 DevOps 工作流,虽然在高级 Office 功能上有局限,但覆盖了 90% 以上的文档生成需求。

二、文档创建与保存

文档的创建与保存是 python-docx 最基础的操作。库提供了灵活的方式创建新文档、打开已有文档、设置文档属性和修改默认样式。掌握这些基础操作才能进入后续的内容编辑。

创建与打开文档

Document() 构造器有两种调用方式:无参调用创建一个带默认空白段落的新文档;传入文件路径则打开一个已有的 .docx 文件进行编辑。python-docx 会保留原文档中所有受支持的元素,但某些高级功能(如宏、ActiveX 控件、嵌入式 Excel 表格等)在重新保存时可能丢失。

from docx import Document # 创建新文档(包含一个默认空白段落) doc = Document() # 打开已有文档进行编辑 doc = Document('existing_document.docx') # 修改内容... doc.add_paragraph('这是新增的内容。') # 保存(可另存为新文件) doc.save('modified_document.docx')

文档属性设置

文档属性(也称为元数据)包括标题、作者、主题、关键词、备注等。这些属性在 Word 的"文件→信息"中可见,对文档管理和搜索很有帮助。通过 core_properties 对象可以访问和设置这些属性。

from docx import Document import datetime doc = Document() # 设置文档核心属性 props = doc.core_properties props.title = '2026年第一季度项目报告' props.author = '张三' props.category = '工作报告' props.comments = '机密文件,仅限管理层查阅' props.content_status = 'Final' props.identifier = 'REP-2026-Q1-001' props.keywords = '项目, 季度, 报告, 2026' props.language = 'zh-CN' props.last_modified_by = '张三' props.revision = 2 props.subject = '第一季度项目进展与财务状况分析' props.version = 'v1.0' # 设置时间属性 props.created = datetime.datetime(2026, 1, 1) props.modified = datetime.datetime.now() doc.save('report_with_properties.docx')

默认样式修改

新建文档时,所有内容默认使用 Normal 样式。通过修改 Normal 样式中的字体、段落格式等属性,可以全局控制文档的默认外观。这在生成统一格式的批量文档时非常有用。

from docx import Document from docx.shared import Pt, Cm, RGBColor from docx.oxml.ns import qn doc = Document() # 修改默认 Normal 样式 style = doc.styles['Normal'] style.font.name = 'Microsoft YaHei' style.font.size = Pt(11) style.font.color.rgb = RGBColor(0x33, 0x33, 0x33) style.paragraph_format.line_spacing = 1.5 style.paragraph_format.space_after = Pt(6) style.paragraph_format.first_line_indent = Cm(0.74) # 设置中文字体 style.element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei') # 修改标题样式 heading_style = doc.styles['Heading 1'] heading_style.font.name = 'Microsoft YaHei' heading_style.font.size = Pt(22) heading_style.font.bold = True heading_style.font.color.rgb = RGBColor(0x2E, 0x7D, 0x32) heading_style.element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei') doc.save('styled_template.docx')

要点总结:Document() 创建或打开文档,save() 保存到磁盘。通过 core_properties 设置文档元数据,通过修改 doc.styles['Normal'] 来改变全局默认格式。建议在创建文档之初就配置好默认样式,避免逐段重复设置格式。

三、段落与文本

段落和文本是 Word 文档中最基础的内容单元。python-docx 将段落作为文本块的组织容器,而段落内部的文本格式变化则通过 Run 对象实现。这种设计允许在同一段落内混合多种格式,例如在一句话中让某个词加粗变红。

段落添加与基本操作

使用 add_paragraph() 方法向文档添加段落。可以传入文本内容和样式参数。段落对象支持丰富的格式设置,包括对齐方式、缩进、行距、段前段后间距等。

from docx import Document from docx.shared import Pt, Cm from docx.enum.text import WD_ALIGN_PARAGRAPH doc = Document() # 添加普通段落 p1 = doc.add_paragraph('这是第一个段落,使用默认Normal样式。') # 添加带样式的段落 p2 = doc.add_paragraph('这是居中对齐的段落。', style='Normal') p2.alignment = WD_ALIGN_PARAGRAPH.CENTER # 设置段落缩进 p3 = doc.add_paragraph('这是一个首行缩进两字符的段落。在中文排版中,首行缩进是常见的格式要求,可以让文档看起来更加规范和专业。') p3.paragraph_format.first_line_indent = Cm(0.74) # 设置行距与段间距 p4 = doc.add_paragraph('这是一个设置了行距和段间距的段落。行距设置为1.5倍,段前间距12磅,段后间距6磅。') p4.paragraph_format.line_spacing = 1.5 p4.paragraph_format.space_before = Pt(12) p4.paragraph_format.space_after = Pt(6) doc.save('paragraph_basics.docx')

Run 对象与文本格式

Run 是段落内具有统一格式的文本片段。一个段落可以包含多个 Run,每个 Run 独立控制字体、大小、颜色、粗斜体、下划线、删除线等属性。这种粒度控制是实现富文本排版的关键。

from docx import Document from docx.shared import Pt, RGBColor from docx.enum.text import WD_UNDERLINE doc = Document() p = doc.add_paragraph() # 添加不同格式的 Run run1 = p.add_run('正常文本 ') run1.font.size = Pt(12) run2 = p.add_run('加粗文本 ') run2.bold = True run2.font.size = Pt(12) run3 = p.add_run('斜体文本 ') run3.italic = True run3.font.size = Pt(12) run4 = p.add_run('红色加粗 ') run4.bold = True run4.font.color.rgb = RGBColor(0xFF, 0x00, 0x00) run4.font.size = Pt(12) run5 = p.add_run('带下划线 ') run5.underline = WD_UNDERLINE.SINGLE run5.font.size = Pt(12) run6 = p.add_run('大号标题风格 ') run6.font.size = Pt(18) run6.font.name = 'Arial' run6.font.color.rgb = RGBColor(0x2E, 0x7D, 0x32) run7 = p.add_run('删除线文本') run7.font.strike = True run7.font.size = Pt(12) doc.save('run_formatting.docx')

对齐方式详解

python-docx 支持五种段落对齐方式:LEFT(左对齐)、CENTER(居中对齐)、RIGHT(右对齐)、JUSTIFY(两端对齐)和 DISTRIBUTE(分散对齐)。两端对齐是中文正式文档中最常用的对齐方式,能使段落左右边缘整齐。

from docx import Document from docx.enum.text import WD_ALIGN_PARAGRAPH doc = Document() p1 = doc.add_paragraph('这是左对齐的文本。在英文排版中较为常见。') p1.alignment = WD_ALIGN_PARAGRAPH.LEFT p2 = doc.add_paragraph('这是居中对齐的文本。通常用于标题或签名行。') p2.alignment = WD_ALIGN_PARAGRAPH.CENTER p3 = doc.add_paragraph('这是右对齐的文本。多用于日期、落款等。') p3.alignment = WD_ALIGN_PARAGRAPH.RIGHT p4 = doc.add_paragraph('这是两端对齐的文本。这是中文正式文档最常用的对齐方式,左右边缘整齐,阅读体验好。在长篇文档中建议使用此对齐方式。') p4.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY doc.save('alignment_demo.docx')

字体与颜色管理

python-docx 的字体管理涉及字体名称、大小、颜色、字符间距等属性。字体名称需区分西文字体(font.name)和中文字体(通过 XML 设置 eastAsia 字体)。颜色使用 RGBColor 对象表示,支持 1600 万色。

from docx import Document from docx.shared import Pt, RGBColor, Cm from docx.oxml.ns import qn doc = Document() p = doc.add_paragraph() # 创建一个兼具中西文字体的 Run run = p.add_run('这是一段混合字体文本:Hello World') run.font.size = Pt(14) # 设置西文字体 run.font.name = 'Times New Roman' # 设置中文字体(通过 XML 操作) run.element.rPr.rFonts.set(qn('w:eastAsia'), 'SimSun') # 设置字体颜色 run.font.color.rgb = RGBColor(0x1A, 0x47, 0x8A) # 设置字符间距 from docx.shared import Twips run.font.character_spacing = Twips(2) doc.save('font_management.docx')

要点总结:段落是内容组织单元(add_paragraph),Run 是格式控制单元(add_run)。在段落级别设置对齐、缩进和间距,在 Run 级别设置字体、大小、颜色和粗斜体。中西文字体需分别设置,中文排版推荐首行缩进 + 两端对齐。

四、标题与目录

标题结构是文档的骨架,良好的标题层级不仅让文档结构清晰,还能自动生成目录和书签,方便读者导航。python-docx 提供了从 Heading 1 到 Heading 9 共 9 级标题样式,同时支持多级编号和自动目录生成。

标题层级管理

使用 add_heading() 方法可以快速添加标题,通过 level 参数控制层级(1-9,对应 Heading 1 到 Heading 9)。标题样式继承基础格式,也可以单独修改。合理设置标题层级是文档结构化的第一步。

from docx import Document from docx.shared import Pt, RGBColor from docx.oxml.ns import qn doc = Document() # 文档主标题(level=0 对应 Title 样式) doc.add_heading('2026年度工作总结报告', level=0) # 一级标题(章) doc.add_heading('第一章 年度概况', level=1) doc.add_paragraph('本章概述2026年度的整体工作情况。') # 二级标题(节) doc.add_heading('1.1 工作业绩回顾', level=2) doc.add_paragraph('全年完成项目共计42个,同比增长15%。') # 三级标题(小节) doc.add_heading('1.1.1 项目完成情况', level=3) doc.add_paragraph('第一季度完成8个,第二季度完成12个...') # 四级标题 doc.add_heading('项目交付周期分析', level=4) doc.add_paragraph('平均交付周期为23个工作日。') # 自定义标题样式 heading_style = doc.styles['Heading 1'] heading_style.font.name = 'Microsoft YaHei' heading_style.font.size = Pt(18) heading_style.font.color.rgb = RGBColor(0x2E, 0x7D, 0x32) heading_style.font.bold = True heading_style.element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei') doc.save('headings_demo.docx')

自动目录生成

python-docx 支持插入 Word 目录域(TOC 域),在 Word 中打开时可以通过"更新域"自动生成目录。目录域可以指定标题层级范围、是否显示页码等参数。

from docx import Document from docx.oxml.ns import qn from docx.oxml import OxmlElement doc = Document() # 添加文档标题 doc.add_heading('项目技术方案', level=0) # 插入目录 paragraph = doc.add_paragraph() run = paragraph.add_run() # 创建 TOC 域(目录深度为3级) fldChar1 = OxmlElement('w:fldChar') fldChar1.set(qn('w:fldCharType'), 'begin') run._element.append(fldChar1) instrText = OxmlElement('w:instrText') instrText.set(qn('xml:space'), 'preserve') instrText.text = ' TOC \\o "1-3" \\h \\z \\u ' run._element.append(instrText) fldChar2 = OxmlElement('w:fldChar') fldChar2.set(qn('w:fldCharType'), 'separate') run._element.append(fldChar2) # 占位文本(在 Word 中更新域后会被替换) run2 = paragraph.add_run('【请在 Word 中右键更新域以生成目录】') run2.font.color.rgb = RGBColor(0x99, 0x99, 0x99) run2.font.size = Pt(10) fldChar3 = OxmlElement('w:fldChar') fldChar3.set(qn('w:fldCharType'), 'end') run._element.append(fldChar3) # 添加分页符,让正文从新页开始 doc.add_page_break() # 添加各级标题 doc.add_heading('第一章 项目背景', level=1) doc.add_heading('1.1 项目概述', level=2) doc.add_paragraph('本项目旨在...') doc.add_heading('1.2 技术选型', level=2) doc.add_paragraph('技术选型遵循...') doc.add_heading('第二章 系统架构', level=1) doc.add_heading('2.1 总体架构', level=2) doc.add_paragraph('系统采用微服务架构...') doc.add_heading('2.1.1 前端架构', level=3) doc.add_paragraph('前端使用 React 框架...') doc.add_heading('第三章 实施计划', level=1) doc.add_paragraph('项目分三个阶段实施...') doc.save('document_with_toc.docx')

标题编号自动化

在正式文档中,标题通常需要自动编号(如"第一章"、"1.1"、"1.1.1")。通过修改标题样式的编号格式(listFormat),可以实现标题的自动编号。

from docx import Document from docx.shared import Pt from docx.oxml.ns import qn from docx.oxml import OxmlElement from copy import deepcopy doc = Document() # 创建多级列表编号定义 numbering_part = doc.part.numbering_part numbering = numbering_part.element # 创建抽象编号定义 abstract_num = OxmlElement('w:abstractNum') abstract_num.set(qn('w:abstractNumId'), '0') # 第一级:第一章,第二级:1.1,第三级:1.1.1 for level in range(3): lvl = OxmlElement('w:lvl') lvl.set(qn('w:ilvl'), str(level)) start = OxmlElement('w:start') start.set(qn('w:val'), '1') lvl.append(start) numFmt = OxmlElement('w:numFmt') numFmt.set(qn('w:val'), 'decimal') lvl.append(numFmt) lvlText = OxmlElement('w:lvlText') if level == 0: lvlText.set(qn('w:val'), '第%1章') elif level == 1: lvlText.set(qn('w:val'), '%1.%2') else: lvlText.set(qn('w:val'), '%1.%2.%3') lvl.append(lvlText) abstract_num.append(lvl) numbering.append(abstract_num) # 上述代码演示了原理,实际项目中建议使用更完善的实现 doc.add_heading('标题一(带编号)', level=1) doc.add_heading('标题1.1', level=2) doc.add_heading('标题1.1.1', level=3) doc.save('numbered_headings.docx')

要点总结:add_heading() 快速添加标题(level 1-9)。通过插入 TOC 域实现自动目录(需在 Word 中更新)。标题编号需要操作 XML 层级实现多级列表定义。建议结构化文档时先规划好标题层级再填充正文内容。

五、列表与编号

列表是组织并列或递进内容的高效方式。python-docx 支持无序列表(项目符号)、有序列表(数字编号)和多级列表,通过内置的 List Bullet、List Number 等样式即可快速应用。

无序列表

无序列表使用 List Bullet 样式,每个段落自动添加项目符号。可以通过修改样式来更换符号样式(圆点、圆圈、方块等)。

from docx import Document from docx.enum.style import WD_STYLE_TYPE from docx.shared import Pt doc = Document() # 最简单的方式:使用 List Bullet 样式 doc.add_paragraph('苹果', style='List Bullet') doc.add_paragraph('香蕉', style='List Bullet') doc.add_paragraph('柑橘', style='List Bullet') # 创建自定义无序列表样式 custom_style = doc.styles.add_style('CustomBullet', WD_STYLE_TYPE.PARAGRAPH) custom_style.base_style = doc.styles['List Bullet'] custom_style.font.size = Pt(11) custom_style.paragraph_format.space_after = Pt(4) doc.add_paragraph('自定义样式的列表项一', style='CustomBullet') doc.add_paragraph('自定义样式的列表项二', style='CustomBullet') doc.save('bullet_list.docx')

有序列表

有序列表使用 List Number 样式,自动生成数字编号。python-docx 支持阿拉伯数字、罗马数字、字母等多种编号格式。

from docx import Document doc = Document() # 使用 List Number 样式 doc.add_paragraph('准备工作环境', style='List Number') doc.add_paragraph('安装 Python 解释器', style='List Number') doc.add_paragraph('安装 pip 包管理器', style='List Number') doc.add_paragraph('安装 python-docx 库', style='List Number') doc.add_paragraph('编写测试脚本', style='List Number') # 带样式的有序列表 doc.add_paragraph('').add_run('操作步骤说明:').bold = True # 自定义有序列表 - 创建新的编号定义 from docx.oxml.ns import qn from docx.oxml import OxmlElement # 添加 Abstract Numbering abstract_num = OxmlElement('w:abstractNum') abstract_num.set(qn('w:abstractNumId'), '101') lvl = OxmlElement('w:lvl') lvl.set(qn('w:ilvl'), '0') start = OxmlElement('w:start') start.set(qn('w:val'), '1') lvl.append(start) numFmt = OxmlElement('w:numFmt') numFmt.set(qn('w:val'), 'decimal') lvl.append(numFmt) lvlText = OxmlElement('w:lvlText') lvlText.set(qn('w:val'), '步骤%1:') lvl.append(lvlText) abstract_num.append(lvl) doc.part.numbering_part.element.append(abstract_num) doc.save('numbered_list.docx')

多级列表

多级列表将无序和有序列表组合为嵌套结构,适用于大纲、技术文档目录等场景。python-docx 通过不同的缩进级别(左缩进)来区分层级。

from docx import Document from docx.shared import Cm doc = Document() # 多级列表 - 通过缩进区分层级 p1 = doc.add_paragraph('第一章 基础概念', style='List Number') p1.paragraph_format.left_indent = Cm(0) p2 = doc.add_paragraph('1.1 Python语言概述', style='List Number') p2.paragraph_format.left_indent = Cm(1.5) p3 = doc.add_paragraph('1.1.1 历史与发展', style='List Number') p3.paragraph_format.left_indent = Cm(3) p4 = doc.add_paragraph('1.1.2 核心特性', style='List Number') p4.paragraph_format.left_indent = Cm(3) p5 = doc.add_paragraph('1.2 开发环境搭建', style='List Number') p5.paragraph_format.left_indent = Cm(1.5) # 混合使用无序和有序 doc.add_paragraph('').add_run('项目清单:').bold = True # 第一层(有序) doc.add_paragraph('基础设施', style='List Number') doc.add_paragraph('服务器采购', style='List Bullet') doc.add_paragraph('网络布线', style='List Bullet') doc.add_paragraph('软件部署', style='List Number') doc.add_paragraph('操作系统安装', style='List Bullet') doc.add_paragraph('数据库配置', style='List Bullet') doc.add_paragraph('应用中间件', style='List Bullet') doc.save('multi_level_list.docx')

列表样式自定义

除了使用内置样式,python-docx 还支持创建完全自定义的列表样式,包括更换项目符号字符、调整编号格式、设置字体颜色等。

from docx import Document from docx.shared import Pt, RGBColor from docx.enum.style import WD_STYLE_TYPE doc = Document() # 创建自定义列表样式 bullet_style = doc.styles.add_style('MyChecklist', WD_STYLE_TYPE.PARAGRAPH) bullet_style.base_style = doc.styles['List Bullet'] bullet_style.font.size = Pt(11) bullet_style.font.color.rgb = RGBColor(0x2E, 0x7D, 0x32) bullet_style.paragraph_format.space_after = Pt(3) bullet_style.paragraph_format.line_spacing = 1.3 # 创建带强调的列表样式 warning_style = doc.styles.add_style('WarningList', WD_STYLE_TYPE.PARAGRAPH) warning_style.base_style = doc.styles['List Bullet'] warning_style.font.color.rgb = RGBColor(0xE6, 0x7E, 0x22) warning_style.font.bold = True doc.add_paragraph('待办事项清单', style='MyChecklist') doc.add_paragraph('完成项目方案撰写', style='MyChecklist') doc.add_paragraph('提交审批流程', style='MyChecklist') doc.add_paragraph('召开项目启动会', style='MyChecklist') doc.add_paragraph('').add_run('注意事项:').bold = True doc.add_paragraph('截止日期前必须提交', style='WarningList') doc.add_paragraph('需经部门负责人签字', style='WarningList') doc.save('custom_list_styles.docx')

要点总结:无序列表用 style='List Bullet',有序列表用 style='List Number'。多级列表通过缩进(left_indent)控制层级。支持创建自定义列表样式更改符号和格式。注意列表编号的连续性受到样式同名和 Abstract Numbering ID 的影响。

六、表格操作

表格是组织和展示结构化数据的重要工具。python-docx 提供了完整的表格操作 API,支持表格创建、行列管理、单元格读写、样式套用和单元格合并拆分等操作。

表格创建与基本操作

使用 add_table() 方法创建表格,指定行数和列数。通过 rows 和 columns 属性访问行列集合,通过 cell(row, col) 访问指定单元格。单元格的内容通过 text 属性读写。

from docx import Document from docx.shared import Pt, Cm doc = Document() doc.add_heading('员工信息表', level=1) # 创建 4 行 4 列的表格 table = doc.add_table(rows=4, cols=4) # 设置表格样式 table.style = 'Table Grid' # 写入表头 headers = ['姓名', '部门', '职位', '入职日期'] for i, header in enumerate(headers): table.cell(0, i).text = header # 写入数据行 data = [ ['张三', '技术部', '高级工程师', '2020-03-15'], ['李四', '市场部', '市场总监', '2019-07-01'], ['王五', '财务部', '财务主管', '2021-01-10'], ] for row_idx, row_data in enumerate(data, start=1): for col_idx, cell_value in enumerate(row_data): table.cell(row_idx, col_idx).text = cell_value # 表头格式加粗 for cell in table.rows[0].cells: for paragraph in cell.paragraphs: for run in paragraph.runs: run.bold = True doc.save('basic_table.docx')

表格样式与美化

python-docx 支持 200 多种内置表格样式(如 'Table Grid'、'Light Shading'、'Medium Shading 1 Accent 1' 等)。还可以通过单元格级操作实现自定义样式,包括背景色、字体、对齐方式等。

from docx import Document from docx.shared import Pt, RGBColor, Cm from docx.enum.table import WD_TABLE_ALIGNMENT from docx.enum.text import WD_ALIGN_PARAGRAPH doc = Document() doc.add_heading('销售数据统计表', level=1) # 创建表格并应用样式 table = doc.add_table(rows=5, cols=5) table.style = 'Medium Shading 1 Accent 1' table.alignment = WD_TABLE_ALIGNMENT.CENTER # 写入数据 headers = ['产品', '第一季度', '第二季度', '第三季度', '第四季度'] for i, h in enumerate(headers): cell = table.cell(0, i) cell.text = h # 居中表头 cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER data = [ ['产品A', '120万', '150万', '180万', '210万'], ['产品B', '85万', '95万', '110万', '130万'], ['产品C', '200万', '220万', '250万', '280万'], ['产品D', '60万', '75万', '90万', '95万'], ] for row_idx, row_data in enumerate(data, start=1): for col_idx, value in enumerate(row_data): cell = table.cell(row_idx, col_idx) cell.text = value cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER # 设置列宽 for row in table.rows: row.cells[0].width = Cm(3) # 设置单元格底纹(高亮特定行) from docx.oxml import OxmlElement shading_elm = OxmlElement('w:shd') shading_elm.set(qn('w:fill'), 'D9E2F3') shading_elm.set(qn('w:val'), 'clear') # 给最后一行(合计行)加背景色 for cell in table.rows[4].cells: cell._element.get_or_add_tcPr().append(shading_elm) doc.save('styled_table.docx')

单元格合并与拆分

单元格合并是复杂表格布局的必备功能。通过 merge() 方法可以将相邻单元格合并为一个单元格,适用于跨列标题、跨行分类等场景。

from docx import Document from docx.shared import Pt, Cm from docx.enum.text import WD_ALIGN_PARAGRAPH doc = Document() doc.add_heading('项目进度表', level=1) # 创建 7 行 4 列的表格 table = doc.add_table(rows=7, cols=4) table.style = 'Table Grid' # 合并第一行(总标题) title_cell = table.cell(0, 0).merge(table.cell(0, 3)) title_cell.text = '2026年度重点项目进度跟踪表' title_cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER for run in title_cell.paragraphs[0].runs: run.bold = True run.font.size = Pt(14) # 表头 headers = ['项目名称', '负责人', '计划完成', '当前状态'] for i, h in enumerate(headers): cell = table.cell(1, i) cell.text = h cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER cell.paragraphs[0].runs[0].bold = True if cell.paragraphs[0].runs else None # 合并分类行 cat_cell = table.cell(2, 0).merge(table.cell(2, 3)) cat_cell.text = 'A类重点项目' cat_cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.LEFT for run in cat_cell.paragraphs[0].runs: run.bold = True # 写入数据 data = [ ['智慧园区平台', '张三', '2026-Q2', '按计划进行'], ['数据中台建设', '李四', '2026-Q3', '需求评审中'], ] for row_idx, row_data in enumerate(data, start=3): for col_idx, value in enumerate(row_data): table.cell(row_idx, col_idx).text = value # 再合并一个分类行 cat_cell2 = table.cell(5, 0).merge(table.cell(5, 3)) cat_cell2.text = 'B类一般项目' cat_cell2.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.LEFT # 最后一行数据 for col_idx, value in enumerate(['移动端优化', '赵六', '2026-Q2', '已上线']): table.cell(6, col_idx).text = value doc.save('merged_table.docx')

行列动态管理

在实际项目中,表格的行列数通常是动态的。python-docx 支持在创建表格后添加行(add_row())和删除行。单元格的读写通过行列索引进行。

from docx import Document from docx.shared import Pt doc = Document() doc.add_heading('动态数据表格', level=1) # 创建只有表头的表格 table = doc.add_table(rows=1, cols=4) table.style = 'Table Grid' # 设置表头 for i, h in enumerate(['ID', '名称', '数量', '单价']): table.cell(0, i).text = h # 模拟从数据库读取数据 records = [ (1, '笔记本电脑', 10, 5999), (2, '显示器', 15, 1999), (3, '键盘', 30, 299), (4, '鼠标', 50, 99), ] # 动态添加行 for record in records: row = table.add_row() for col_idx, value in enumerate(record): row.cells[col_idx].text = str(value) # 删除最后一行(演示删除操作) # 注意:python-docx 没有直接的 delete_row 方法,需要通过 XML 操作 # 这里换一种方式:不添加最后一行的数据 # 实际上 add_row 已经添加了,我们只添加前3条 # 重新创建表格会更干净,这里演示 add_row 的用法 doc.save('dynamic_table.docx')

要点总结:add_table(rows, cols) 创建表格,cell(row, col).text 读写数据。200+ 内置样式通过 table.style 设置。merge() 合并单元格实现复杂布局。add_row() 动态扩展行数。表头加粗和数据居中是表格美化的常用操作。

七、图片与图形

图片和图形是增强文档表现力的重要元素。python-docx 支持在文档中插入图片、设置图片大小和位置,同时还提供基本的图形对象操作能力。

图片插入与尺寸控制

使用 add_picture() 方法插入图片,支持常见的图片格式(PNG、JPG、GIF、BMP 等)。通过 Inches、Cm、Pt 等单位类控制图片尺寸,可以同时指定宽度和高度(等比例缩放)或只指定一个维度(自动保持宽高比)。

from docx import Document from docx.shared import Inches, Cm, Pt, Emu doc = Document() doc.add_heading('产品说明文档', level=1) doc.add_paragraph('以下是产品外观图:') # 插入图片(指定宽度,自动等比例缩放高度) pic = doc.add_picture('product_image.png', width=Inches(4)) # 查看图片原始尺寸和调整后尺寸 print(f"图片宽度: {pic.width}, 高度: {pic.height}") # 精确控制图片尺寸 doc.add_paragraph('以下是产品细节图(指定精确尺寸):') pic2 = doc.add_picture('detail_image.png') pic2.width = Cm(8) pic2.height = Cm(6) # 在表格中插入图片 table = doc.add_table(rows=2, cols=2) table.style = 'Table Grid' table.cell(0, 0).text = '产品正面' table.cell(0, 1).text = '产品侧面' # 表格单元格中插入图片需要获取单元格的段落 # cell.paragraphs[0] 然后添加 run 并插入图片 # 注意:python-docx 不支持直接在单元格段落中 add_picture # 需要使用底层 XML 操作或调整方法 # 一个变通方法:在表格上方插入图片后通过表格排列 doc.save('images_demo.docx')

图片位置与环绕方式

Word 中的图片可以设置不同的文字环绕方式(嵌入型、四周型、上下型等)。python-docx 通过调整图片的 inline 或 anchor 属性来控制位置。默认图片为嵌入型(inline),随文字移动。

from docx import Document from docx.shared import Inches, Cm from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.oxml.ns import qn from docx.oxml import OxmlElement doc = Document() doc.add_heading('产品使用手册', level=1) doc.add_paragraph('以下是产品安装示意图(居中显示):') # 插入图片并居中 pic = doc.add_picture('installation_guide.png', width=Inches(3.5)) # 获取图片所在段落并居中 last_paragraph = doc.paragraphs[-1] last_paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER # 在图片下方添加说明文字 caption = doc.add_paragraph('图1:产品安装示意图') caption.alignment = WD_ALIGN_PARAGRAPH.CENTER for run in caption.runs: run.font.size = Pt(9) run.font.color.rgb = RGBColor(0x66, 0x66, 0x66) # 在段落中插入图片(行内,随文字排版) p = doc.add_paragraph('请参考右侧的参考图例进行操作,') # 这里需要在 run 级别插入图片 # 注意:python-docx 不支持 run.add_picture,需要扩展操作 # 替代方案:在段落下方单独插入图片 doc.add_paragraph('以下是多图并排展示:') doc.save('image_positioning.docx')

图表与形状

python-docx 对图表和形状的支持相对有限。复杂图表建议使用 matplotlib 生成图片后再插入文档。对于基本形状,可以通过操作底层 XML 添加。

from docx import Document from docx.shared import Inches import matplotlib.pyplot as plt import numpy as np # 第一步:使用 matplotlib 生成统计图 categories = ['Q1', 'Q2', 'Q3', 'Q4'] values = [125, 180, 210, 265] plt.figure(figsize=(6, 3.5)) plt.bar(categories, values, color=['#2E7D32', '#388E3C', '#43A047', '#4CAF50']) plt.title('2026年度季度销售额', fontsize=14) plt.xlabel('季度') plt.ylabel('销售额(万元)') for i, v in enumerate(values): plt.text(i, v + 3, str(v), ha='center', fontsize=11) # 保存图表为图片 plt.savefig('sales_chart.png', dpi=150, bbox_inches='tight') plt.close() # 第二步:将图片插入 Word 文档 doc = Document() doc.add_heading('销售数据可视化报告', level=1) doc.add_paragraph('下图为2026年度各季度销售额柱状图:') doc.add_picture('sales_chart.png', width=Inches(5.2)) # 添加图注 caption = doc.add_paragraph('图2:2026年度季度销售额统计') caption.alignment = WD_ALIGN_PARAGRAPH.CENTER doc.save('chart_in_doc.docx')

要点总结:add_picture() 插入图片,Inches/Cm 控制尺寸。图片嵌入段落可通过设置段落对齐方式调整位置。复杂图表推荐 matplotlib 生成后插入。python-docx 对形状和图表原生支持有限,图片方式更加灵活稳定。

八、页面布局

页面布局控制是专业文档排版的关键环节。python-docx 通过 Section(节)对象管理页面设置,支持纸张大小、页边距、页面方向、分节符、页眉页脚和页码等布局元素的精确控制。

页面设置

每个 Section 对象包含独立的页面设置属性,包括页面宽度和高度(paper size)、上下左右边距、页面方向(纵向/横向)等。通过修改 section 的相应属性可以灵活控制页面布局。

from docx import Document from docx.shared import Cm, Mm, Inches from docx.enum.section import WD_ORIENT doc = Document() # 获取第一个节 section = doc.sections[0] # 设置 A4 纸张 section.page_width = Cm(21) section.page_height = Cm(29.7) # 设置页边距 section.top_margin = Cm(2.54) section.bottom_margin = Cm(2.54) section.left_margin = Cm(3.17) section.right_margin = Cm(3.17) # 设置页面方向(默认纵向) section.orientation = WD_ORIENT.PORTRAIT # 添加文档内容 doc.add_heading('页面布局示例', level=1) doc.add_paragraph('本节使用标准 A4 纸张,上下边距2.54cm,左右边距3.17cm。') # 添加一个新节(横向页面) new_section = doc.add_section() new_section.orientation = WD_ORIENT.LANDSCAPE new_section.page_width = Cm(29.7) new_section.page_height = Cm(21) new_section.top_margin = Cm(2) new_section.bottom_margin = Cm(2) new_section.left_margin = Cm(2.5) new_section.right_margin = Cm(2.5) doc.add_heading('横向页面', level=1) doc.add_paragraph('此页面使用横向布局,适合放置宽表格或大图。') # 恢复纵向 third_section = doc.add_section() third_section.orientation = WD_ORIENT.PORTRAIT third_section.page_width = Cm(21) third_section.page_height = Cm(29.7) doc.add_heading('回到纵向', level=1) doc.add_paragraph('后续内容恢复为纵向布局。') doc.save('page_setup.docx')

分页控制

通过 add_page_break() 和分节符控制文档的分页行为。add_page_break() 在当前位置插入分页符,将后续内容推到下一页。分节符则创建新的 Section,允许独立的页面设置。

from docx import Document from docx.shared import Cm from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.oxml.ns import qn from docx.oxml import OxmlElement doc = Document() doc.add_heading('第一章 绪论', level=1) doc.add_paragraph('这是绪论内容...') # 插入分页符 doc.add_page_break() doc.add_heading('第二章 技术方案', level=1) doc.add_paragraph('这是技术方案内容...') # 在段落内强制分页(段落前分页) from docx.enum.text import WD_BREAK p = doc.add_paragraph('此段落将在下一页继续。') run = p.add_run() run.add_break(WD_BREAK.PAGE) doc.add_paragraph('这是新页的内容。') # 使用分节符(不同页面设置) new_section = doc.add_section() new_section.left_margin = Cm(4) # 更宽的左边距(适合装订) new_section.right_margin = Cm(2) doc.add_heading('附录 A:参考文献', level=1) doc.add_paragraph('参考文献列表...') doc.save('page_breaks.docx')

页眉、页脚与页码

页眉和页脚通过 Section 的 header 和 footer 属性访问。每个 Section 有独立的页眉/页脚,可以设置首页不同、奇偶页不同等选项。页码通过插入 PAGE 域实现。

from docx import Document from docx.shared import Pt, Cm, RGBColor from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.oxml.ns import qn from docx.oxml import OxmlElement doc = Document() section = doc.sections[0] # 设置页眉 header = section.header header_para = header.paragraphs[0] header_para.text = '2026年度技术白皮书' header_para.alignment = WD_ALIGN_PARAGRAPH.CENTER for run in header_para.runs: run.font.size = Pt(9) run.font.color.rgb = RGBColor(0x66, 0x66, 0x66) # 设置页脚(含页码) footer = section.footer footer_para = footer.paragraphs[0] footer_para.alignment = WD_ALIGN_PARAGRAPH.CENTER # 添加页码域 run = footer_para.add_run() run.font.size = Pt(9) # 插入页码字段代码 fldChar1 = OxmlElement('w:fldChar') fldChar1.set(qn('w:fldCharType'), 'begin') run._element.append(fldChar1) instrText = OxmlElement('w:instrText') instrText.set(qn('xml:space'), 'preserve') instrText.text = ' PAGE ' run._element.append(instrText) fldChar2 = OxmlElement('w:fldChar') fldChar2.set(qn('w:fldCharType'), 'separate') run._element.append(fldChar2) run2 = footer_para.add_run('1') run2.font.size = Pt(9) fldChar3 = OxmlElement('w:fldChar') fldChar3.set(qn('w:fldCharType'), 'end') run._element.append(fldChar3) # 添加 "第 X 页 / 共 Y 页" 格式 run3 = footer_para.add_run(' / ') run3.font.size = Pt(9) run4 = footer_para.add_run() run4.font.size = Pt(9) fldChar4 = OxmlElement('w:fldChar') fldChar4.set(qn('w:fldCharType'), 'begin') run4._element.append(fldChar4) instrText2 = OxmlElement('w:instrText') instrText2.set(qn('xml:space'), 'preserve') instrText2.text = ' NUMPAGES ' run4._element.append(instrText2) fldChar5 = OxmlElement('w:fldChar') fldChar5.set(qn('w:fldCharType'), 'separate') run4._element.append(fldChar5) run5 = footer_para.add_run('1') run5.font.size = Pt(9) fldChar6 = OxmlElement('w:fldChar') fldChar6.set(qn('w:fldCharType'), 'end') run4._element.append(fldChar6) # 设置首页不同 section.different_first_page_header_footer = True # 首页页眉(不同) first_header = section.first_page_header first_para = first_header.paragraphs[0] first_para.text = '(封面页)' first_para.alignment = WD_ALIGN_PARAGRAPH.CENTER # 添加正文内容 doc.add_heading('文档正文', level=1) doc.add_paragraph('这是正文第一页的内容。') doc.save('header_footer.docx')

要点总结:Section 控制页面布局,add_section() 创建分节。header/footer 属性访问页眉页脚,页码通过 PAGE 域实现。different_first_page_header_footer 控制首页独立。不同节可以有不同的页面方向、边距和页眉页脚,适用于混合排版场景。

九、样式与主题

样式是 Word 文档格式管理的核心机制。python-docx 支持创建、修改和应用字符样式、段落样式、表格样式和列表样式。通过样式系统可以确保文档格式的一致性和可维护性。

样式对象模型

python-docx 的样式系统包含四种样式类型:段落样式(WD_STYLE_TYPE.PARAGRAPH)控制段落级别和字体级别的所有格式;字符样式(WD_STYLE_TYPE.CHARACTER)仅控制字体级别的格式,不涉及段落布局;表格样式(WD_STYLE_TYPE.TABLE)控制表格的整体外观;列表样式(WD_STYLE_TYPE.LIST)控制列表的编号和符号。所有的样式通过 doc.styles 集合进行管理。

from docx import Document from docx.shared import Pt, RGBColor, Cm from docx.enum.style import WD_STYLE_TYPE from docx.oxml.ns import qn doc = Document() # 创建一个自定义段落样式 custom_style = doc.styles.add_style('CustomBody', WD_STYLE_TYPE.PARAGRAPH) # 设置字体属性 custom_style.font.name = 'Microsoft YaHei' custom_style.font.size = Pt(11) custom_style.font.color.rgb = RGBColor(0x33, 0x33, 0x33) custom_style.italic = False custom_style.font.bold = False # 设置中文字体 custom_style.element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei') # 设置段落格式 custom_style.paragraph_format.first_line_indent = Cm(0.74) custom_style.paragraph_format.line_spacing = 1.5 custom_style.paragraph_format.space_after = Pt(6) # 创建强调样式 emphasis_style = doc.styles.add_style('EmphasisText', WD_STYLE_TYPE.CHARACTER) emphasis_style.font.name = 'Microsoft YaHei' emphasis_style.font.size = Pt(11) emphasis_style.font.color.rgb = RGBColor(0xE6, 0x7E, 0x22) emphasis_style.font.bold = True emphasis_style.element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei') # 应用自定义样式 doc.add_paragraph('这是使用自定义段落样式的正文内容。', style='CustomBody') p = doc.add_paragraph() p.style = doc.styles['CustomBody'] run = p.add_run('这是普通文本,') run2 = p.add_run('这是使用强调样式的文本。') run2.style = doc.styles['EmphasisText'] doc.save('custom_styles.docx')

样式继承与修改

样式之间具有继承关系。Normal 样式是所有段落样式和字符样式的基础基准。修改 Normal 样式会级联影响所有基于它的样式。通过 style.base_style 属性可以查看或设置样式的基样式。

from docx import Document from docx.shared import Pt, RGBColor, Cm from docx.enum.style import WD_STYLE_TYPE from docx.oxml.ns import qn doc = Document() # 修改基础 Normal 样式(影响全局) normal = doc.styles['Normal'] normal.font.name = 'Microsoft YaHei' normal.font.size = Pt(11) normal.paragraph_format.line_spacing = 1.5 normal.paragraph_format.space_after = Pt(6) normal.element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei') # 创建基于 Normal 的派生样式 note_style = doc.styles.add_style('Note', WD_STYLE_TYPE.PARAGRAPH) note_style.base_style = doc.styles['Normal'] # 继承 Normal note_style.font.size = Pt(10) note_style.font.color.rgb = RGBColor(0x66, 0x66, 0x66) note_style.paragraph_format.left_indent = Cm(1) note_style.paragraph_format.first_line_indent = Cm(0) # 创建标题2的变体 h2_style = doc.styles['Heading 2'] h2_style.font.name = 'Microsoft YaHei' h2_style.font.color.rgb = RGBColor(0x2E, 0x7D, 0x32) h2_style.element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei') # 查看样式继承链 print(f"Note 样式的基样式: {note_style.base_style.name}") print(f"Normal 样式的基样式: {normal.base_style}") # 应用样式 doc.add_heading('样式继承示例', level=2) doc.add_paragraph('这是 Normal 样式的文本。') doc.add_paragraph('这是一条注释文本,继承了 Normal 的基础设置。', style='Note') doc.save('style_inheritance.docx')

主题与颜色方案

Word 主题定义了文档的颜色、字体和效果方案。python-docx 可以通过修改主题元素来统一文档的视觉风格。主题颜色(如 Accent 1、Accent 2)可以在样式中引用,实现一键换色。

from docx import Document from docx.shared import Pt, RGBColor from docx.oxml.ns import qn from docx.oxml import OxmlElement from lxml import etree doc = Document() # 修改文档主题颜色 theme = doc.part.theme_part.element # 查找主题颜色元素 namespace = 'http://schemas.openxmlformats.org/drawingml/2006/main' clrScheme = theme.find(f'{{{namespace}}}theme/{{{namespace}}}themeElements/{{{namespace}}}clrScheme') if clrScheme is not None: print(f"当前主题颜色方案: {clrScheme.get('name')}") # 在样式中使用主题颜色(而非固定 RGB) h1_style = doc.styles['Heading 1'] h1_style.font.name = 'Microsoft YaHei' h1_style.element.rPr.rFonts.set(qn('w:eastAsia'), 'Microsoft YaHei') # 设置字体颜色为主题 Accent 1 from docx.oxml import OxmlElement # 创建使用主题颜色的 元素 color_elem = OxmlElement('w:color') color_elem.set(qn('w:val'), '2E7D32') color_elem.set(qn('w:themeColor'), 'accent1') # 替换原有颜色设置 rPr = h1_style.element.get_or_add_rPr() existing_color = rPr.find(qn('w:color')) if existing_color is not None: rPr.remove(existing_color) rPr.append(color_elem) # 应用样式 doc.add_heading('主题颜色示例', level=1) doc.add_paragraph('标题使用了主题 Accent 1 颜色。') doc.save('theme_demo.docx')

要点总结:样式系统包括段落、字符、表格和列表四种类型。通过 doc.styles.add_style() 创建自定义样式,base_style 控制继承关系。修改 Normal 样式可全局影响文档。主题颜色通过 themeColor 属性引用,便于后期整体换色。

十、实战案例

理论知识最终要落实到实际应用。本章通过三个完整的实战案例,展示 python-docx 在日常办公自动化中的典型用法:自动生成项目报告、创建标准化合同文档、批量生成简历模板。

案例一:自动生成项目报告

项目报告是职场中最常见的文档类型之一。以下代码演示了如何从结构化数据自动生成包含封面、目录、图表和正文的完整报告。该方案可集成到 CI/CD 流程中,实现定时自动生成周报/月报。

from docx import Document from docx.shared import Pt, Inches, Cm, RGBColor from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.oxml.ns import qn from docx.oxml import OxmlElement import datetime def generate_project_report(project_name, author, data): """自动生成项目报告""" doc = Document() # === 页面设置 === section = doc.sections[0] section.top_margin = Cm(2.54) section.bottom_margin = Cm(2.54) section.left_margin = Cm(3.17) section.right_margin = Cm(3.17) # === 封面 === for _ in range(6): doc.add_paragraph('') title = doc.add_paragraph() title.alignment = WD_ALIGN_PARAGRAPH.CENTER run = title.add_run(f'{project_name}\n项目报告') run.font.size = Pt(28) run.font.color.rgb = RGBColor(0x2E, 0x7D, 0x32) run.font.bold = True doc.add_paragraph('') info = doc.add_paragraph() info.alignment = WD_ALIGN_PARAGRAPH.CENTER info.add_run(f'作者:{author}\n日期:{datetime.date.today().strftime("%Y年%m月%d日")}').font.size = Pt(14) doc.add_page_break() # === 目录页 === doc.add_heading('目录', level=1) toc_para = doc.add_paragraph() run = toc_para.add_run() run.font.color.rgb = RGBColor(0x99, 0x99, 0x99) fldChar = OxmlElement('w:fldChar') fldChar.set(qn('w:fldCharType'), 'begin') run._element.append(fldChar) instrText = OxmlElement('w:instrText') instrText.set(qn('xml:space'), 'preserve') instrText.text = ' TOC \\o "1-3" \\h \\z \\u ' run._element.append(instrText) fldChar2 = OxmlElement('w:fldChar') fldChar2.set(qn('w:fldCharType'), 'separate') run._element.append(fldChar2) toc_para.add_run('(请在Word中右键更新域)') fldChar3 = OxmlElement('w:fldChar') fldChar3.set(qn('w:fldCharType'), 'end') run._element.append(fldChar3) doc.add_page_break() # === 第一章:概述 === doc.add_heading(f'第一章 {project_name} 概述', level=1) doc.add_paragraph(f'本报告对{project_name}项目的执行情况进行全面总结。') doc.add_paragraph(f'项目周期:{data["start_date"]} 至 {data["end_date"]}') doc.add_paragraph(f'项目状态:{data["status"]}') # === 第二章:执行情况 === doc.add_heading('第二章 执行情况', level=1) doc.add_heading('2.1 任务完成清单', level=2) table = doc.add_table(rows=len(data['tasks']) + 1, cols=3) table.style = 'Light Shading Accent 1' for i, h in enumerate(['任务名称', '负责人', '完成状态']): table.cell(0, i).text = h for row_idx, task in enumerate(data['tasks'], start=1): table.cell(row_idx, 0).text = task['name'] table.cell(row_idx, 1).text = task['owner'] table.cell(row_idx, 2).text = task['status'] # === 第三章:数据分析 === doc.add_heading('第三章 数据分析', level=1) doc.add_paragraph(f'本期共完成 {data["total_tasks"]} 项任务,') doc.add_paragraph(f'其中已完成 {data["completed_tasks"]} 项,完成率 {data["completion_rate"]}%。') key_point = doc.add_paragraph() key_point.style = doc.styles['Normal'] run = key_point.add_run(f'核心指标:项目整体健康度为 {data["health_score"]}/10,') run.bold = True run.font.color.rgb = RGBColor(0x2E, 0x7D, 0x32) key_point.add_run('建议继续保持当前执行节奏。') # === 保存 === filename = f'{project_name}_报告_{datetime.date.today().strftime("%Y%m%d")}.docx' doc.save(filename) print(f"报告已生成:{filename}") return filename # 使用示例 data = { 'start_date': '2026-01-01', 'end_date': '2026-03-31', 'status': '进行中', 'total_tasks': 20, 'completed_tasks': 16, 'completion_rate': '80%', 'health_score': 8.5, 'tasks': [ {'name': '需求调研', 'owner': '张三', 'status': '已完成'}, {'name': '系统设计', 'owner': '李四', 'status': '已完成'}, {'name': '前端开发', 'owner': '王五', 'status': '进行中'}, {'name': '后端开发', 'owner': '赵六', 'status': '进行中'}, {'name': '测试部署', 'owner': '钱七', 'status': '未开始'}, ] } generate_project_report('智慧园区平台', '张三丰', data)

案例二:标准化合同文档生成

合同文档通常有固定的模板结构和条款,只需填充可变数据即可。以下示例展示了如何从模板生成标准化的服务合同,包含合同编号、签约方信息、服务条款、签章区域等结构化内容。

from docx import Document from docx.shared import Pt, Inches, Cm, RGBColor from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.enum.table import WD_TABLE_ALIGNMENT import datetime def generate_contract(contract_data): """生成标准化服务合同""" doc = Document() # 默认样式设置 style = doc.styles['Normal'] style.font.name = 'SimSun' style.font.size = Pt(12) style.paragraph_format.line_spacing = 1.5 # === 合同标题 === title = doc.add_paragraph() title.alignment = WD_ALIGN_PARAGRAPH.CENTER run = title.add_run('技术服务合同') run.font.size = Pt(22) run.font.bold = True run.font.name = 'SimHei' # 合同编号 contract_id = doc.add_paragraph() contract_id.alignment = WD_ALIGN_PARAGRAPH.RIGHT contract_id.add_run(f'合同编号:{contract_data["contract_no"]}').font.size = Pt(10) doc.add_paragraph() # === 签约方信息 === doc.add_heading('甲方(委托方)', level=2) doc.add_paragraph(f'单位名称:{contract_data["party_a"]["name"]}') doc.add_paragraph(f'法定代表人:{contract_data["party_a"]["legal_rep"]}') doc.add_paragraph(f'联系地址:{contract_data["party_a"]["address"]}') doc.add_paragraph(f'联系电话:{contract_data["party_a"]["phone"]}') doc.add_heading('乙方(服务方)', level=2) doc.add_paragraph(f'单位名称:{contract_data["party_b"]["name"]}') doc.add_paragraph(f'法定代表人:{contract_data["party_b"]["legal_rep"]}') doc.add_paragraph(f'联系地址:{contract_data["party_b"]["address"]}') doc.add_paragraph(f'联系电话:{contract_data["party_b"]["phone"]}') doc.add_paragraph() # === 条款正文 === clauses = contract_data['clauses'] for i, clause in enumerate(clauses, start=1): doc.add_heading(f'第{i}条 {clause["title"]}', level=2) for paragraph_text in clause['content']: doc.add_paragraph(paragraph_text) doc.add_paragraph() # === 签章区域 === doc.add_paragraph('本协议一式两份,甲乙双方各执一份,具有同等法律效力。') doc.add_paragraph('') # 签章表格 sign_table = doc.add_table(rows=1, cols=2) sign_table.alignment = WD_TABLE_ALIGNMENT.CENTER for i, party in enumerate(['甲方(盖章):', '乙方(盖章):']): cell = sign_table.cell(0, i) cell.text = '' cell.paragraphs[0].add_run(f'\n\n{party}\n\n').bold = True cell.paragraphs[0].add_run(f'授权代表签字:________\n') cell.paragraphs[0].add_run(f'日期:____年____月____日\n\n') # === 保存 === filename = f'合同_{contract_data["contract_no"]}.docx' doc.save(filename) print(f"合同已生成:{filename}") return filename # 使用示例 contract_data = { 'contract_no': 'JSFW-2026-001', 'party_a': { 'name': '上海佼艾科技有限公司', 'legal_rep': '李四', 'address': '上海市浦东新区张江高科技园区', 'phone': '021-12345678', }, 'party_b': { 'name': '北京云帆信息技术有限公司', 'legal_rep': '王五', 'address': '北京市海淀区中关村软件园', 'phone': '010-87654321', }, 'clauses': [ { 'title': '服务内容与范围', 'content': [ '乙方根据甲方需求,提供以下技术服务:系统架构设计、核心模块开发、性能优化与技术支持。', '具体服务内容以附件《技术规格说明书》为准,该附件为本合同不可分割的组成部分。', ], }, { 'title': '服务期限', 'content': [ '本合同服务期限自签字之日起12个月。', '服务期满前30日,双方可协商续签事宜。', ], }, { 'title': '服务费用与支付方式', 'content': [ '本合同总金额为人民币伍拾万元整(¥500,000.00)。', '支付方式:合同签订后支付30%,中期验收后支付40%,终验合格后支付30%。', ], }, ], } generate_contract(contract_data)

案例三:批量简历模板生成

在人力资源场景中,经常需要从结构化数据批量生成格式统一的简历或档案表。以下示例展示如何将 CSV/Excel 中的人员数据自动转换为格式规范的 Word 简历文档。

from docx import Document from docx.shared import Pt, Inches, Cm, RGBColor from docx.enum.text import WD_ALIGN_PARAGRAPH from docx.enum.table import WD_TABLE_ALIGNMENT from docx.oxml.ns import qn import os def generate_resume(person_data, output_path): """生成个人简历""" doc = Document() # === 个人基本信息 === section = doc.sections[0] section.top_margin = Cm(2) section.bottom_margin = Cm(2) section.left_margin = Cm(2.5) section.right_margin = Cm(2.5) # 姓名(大标题) name_para = doc.add_paragraph() name_para.alignment = WD_ALIGN_PARAGRAPH.CENTER run = name_para.add_run(person_data['name']) run.font.size = Pt(26) run.font.bold = True run.font.name = 'Microsoft YaHei' run.font.color.rgb = RGBColor(0x2E, 0x7D, 0x32) # 求职意向 target = doc.add_paragraph() target.alignment = WD_ALIGN_PARAGRAPH.CENTER target.add_run(f'求职意向:{person_data["target"]}').font.size = Pt(12) # 联系方式信息表 info_table = doc.add_table(rows=1, cols=4) info_table.style = 'Light Shading Accent 1' info_table.alignment = WD_TABLE_ALIGNMENT.CENTER info_fields = [ ('电话', person_data['phone']), ('邮箱', person_data['email']), ('学历', person_data['degree']), ('经验', person_data['experience']), ] for i, (label, value) in enumerate(info_fields): cell = info_table.cell(0, i) cell.text = f'{label}:{value}' cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER doc.add_paragraph() # === 教育背景 === doc.add_heading('教育背景', level=2) edu = person_data['education'] p = doc.add_paragraph() run = p.add_run(f'{edu["school"]} | {edu["major"]} | {edu["degree"]} | {edu["period"]}') run.font.size = Pt(11) # === 工作经历 === doc.add_heading('工作经历', level=2) for work in person_data['work_experience']: p = doc.add_paragraph() run = p.add_run(f'{work["company"]} | {work["position"]} | {work["period"]}') run.bold = True run.font.size = Pt(11) for detail in work['details']: bp = doc.add_paragraph(style='List Bullet') bp.add_run(detail).font.size = Pt(10) # === 专业技能 === doc.add_heading('专业技能', level=2) for skill in person_data['skills']: doc.add_paragraph(skill, style='List Bullet') # === 项目经验 === doc.add_heading('项目经验', level=2) for proj in person_data['projects']: p = doc.add_paragraph() run = p.add_run(f'{proj["name"]} | {proj["role"]} | {proj["period"]}') run.bold = True run.font.size = Pt(11) p2 = doc.add_paragraph(proj['description']) p2.paragraph_format.first_line_indent = Cm(0) # 保存文件 filename = os.path.join(output_path, f'{person_data["name"]}_简历.docx') doc.save(filename) print(f"简历已生成:{filename}") return filename # 单个简历数据 candidate = { 'name': '张三', 'target': '高级Python工程师', 'phone': '138-0000-0001', 'email': 'zhangsan@example.com', 'degree': '硕士', 'experience': '5年', 'education': { 'school': '上海交通大学', 'major': '计算机科学与技术', 'degree': '硕士', 'period': '2018-2021', }, 'work_experience': [ { 'company': '某大型互联网公司', 'position': 'Python后端工程师', 'period': '2021-2025', 'details': [ '负责核心业务系统的架构设计与开发,日处理请求量超百万', '主导微服务迁移项目,将单体应用拆分为12个微服务', '优化数据库查询性能,平均响应时间降低60%', ], }, ], 'skills': [ '精通 Python 语言及 Django/FastAPI 框架', '熟悉 PostgreSQL、Redis、MongoDB 等数据库', '掌握 Docker、Kubernetes 容器化部署', '熟悉 RESTful API 设计与微服务架构', ], 'projects': [ { 'name': '智慧物流平台', 'role': '技术负责人', 'period': '2023-2024', 'description': '负责平台技术选型、架构设计和核心模块开发。系统支持日均50万订单处理,实现智能路径规划和实时调度功能。', }, ], } generate_resume(candidate, '.')

综合应用:批量模板化生成

在实际企业应用中,最强大的场景是将模板文件与数据分离:预先设计好 .docx 模板(包含占位符),然后使用 python-docx 读取模板、替换占位符、生成最终文档。这种方式将文档设计和数据填充解耦,非技术人员也能参与模板设计。

from docx import Document from docx.shared import Pt, RGBColor def fill_template(template_path, replacements, output_path): """从模板生成文档,替换占位符""" doc = Document(template_path) # 替换段落中的占位符 for paragraph in doc.paragraphs: for key, value in replacements.items(): if key in paragraph.text: # 逐个替换 run 中的文本 for run in paragraph.runs: if key in run.text: run.text = run.text.replace(key, str(value)) # 替换表格中的占位符 for table in doc.tables: for row in table.rows: for cell in row.cells: for key, value in replacements.items(): if key in cell.text: for paragraph in cell.paragraphs: for run in paragraph.runs: if key in run.text: run.text = run.text.replace(key, str(value)) doc.save(output_path) print(f"文档已生成:{output_path}") # 使用示例 replacements = { '{{员工姓名}}': '张三', '{{部门}}': '技术研发部', '{{职位}}': '高级工程师', '{{入职日期}}': '2020-03-15', '{{工号}}': 'EMP-2020-0089', '{{当前日期}}': '2026-05-05', } # fill_template('员工信息模板.docx', replacements, '张三_个人档案.docx') print("模板填充函数已定义。") # 批量生成示例 employees = [ {'name': '张三', 'dept': '技术部', 'title': '高级工程师', 'date': '2020-03-15'}, {'name': '李四', 'dept': '市场部', 'title': '市场总监', 'date': '2019-07-01'}, {'name': '王五', 'dept': '财务部', 'title': '财务主管', 'date': '2021-01-10'}, ] for emp in employees: emp_replacements = { '{{员工姓名}}': emp['name'], '{{部门}}': emp['dept'], '{{职位}}': emp['title'], '{{入职日期}}': emp['date'], } print(f"准备生成 {emp['name']} 的文档...") # fill_template('模板.docx', emp_replacements, f"{emp['name']}_档案.docx") print("批量生成准备就绪。")

要点总结:实战中应始终遵循"数据与展示分离"原则。使用函数封装文档生成逻辑,将可变数据作为参数传入。合同、简历等标准文档建议配合模板使用,结合 python-docx 的编程控制能力。批量生成时注意文件命名规范和异常处理,建议配合日志记录和错误处理机制。