← 返回自动化办公目录
← 返回学习笔记首页
专题: 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 的编程控制能力。批量生成时注意文件命名规范和异常处理,建议配合日志记录和错误处理机制。