1. Python-docx库概述与安装
python-docx是一个纯Python实现的第三方库,专门用于创建和修改Microsoft Word的.docx格式文档。这个库最大的优势在于它不需要依赖Microsoft Word软件即可运行,具备优秀的跨平台特性,可以在Windows、Mac、Linux等系统上使用。
注意:python-docx仅兼容.docx格式(对应Word 2007及以上版本),不支持旧版的.doc格式文件。这是因为.docx是基于XML的开放压缩格式,而.doc是二进制私有格式,前者体积更小、兼容性更优。
安装python-docx非常简单,使用pip命令即可:
bash复制pip install python-docx
截至本文撰写时,python-docx的稳定版本为1.2.0。安装完成后,你可以通过以下方式验证安装是否成功:
python复制import docx
print(docx.__version__) # 应该输出1.2.0或更高版本
2. Python-docx的核心对象模型
Python-docx中的Word文档内存对象模型采用树状结构分层映射文档元素,使得程序能够精准控制文档的内容、格式与布局。理解这个对象模型是高效使用python-docx的关键。
2.1 文档对象结构
文档的树状结构示意如下:
code复制Document(文档)
├── Sections(节)
├── Paragraphs(段落)
│ ├── Runs(文本片段)
│ └── InlineShapes(内联形状,如图片)
├── Tables(表格)
│ ├── Rows(行)
│ │ └── Cells(单元格)
│ │ └── Paragraphs(单元格内的段落)
└── Core Properties(文档属性)
2.2 核心对象功能说明
| 核心对象 | 代表含义 | 在文档树中的位置 | 主要功能与说明 |
|---|---|---|---|
| Document | 整个Word文档对象 | 根对象 | 用于打开或创建一个.docx文件 |
| Sections | 文档的节 | Document.sections | 管理页面设置(如页边距、纸张方向) |
| Paragraph | 段落 | Document.paragraphs或Table.cell.paragraphs | 文档的基本单元由一个或多个Run组成,并拥有统一的段落格式 |
| Run | 具有相同格式的连续文本 | Paragraph.runs | 格式控制的最小单位,可以对Run单独设置字体、大小等字符级格式 |
| Table | 表格 | Document.tables | 代表文档中的一个表格,由行(Table.rows)、列(Table.columns)和单元格(Table.cell)组成 |
| Cell | 表格单元格 | Table.cell(row,col) | 每个Cell本身可以包含多个Paragraph,就像一个微缩文档 |
| InlineShape | 内嵌形状(如图片) | Paragraph.add_picture()创建 | 代表文档中与文本在同一层的图形对象,最常用的是图片 |
| Styles | 样式集合 | Document.styles | 管理文档中定义的所有样式(如"标题1"、"正文"等) |
3. 基础文档操作实战
3.1 创建新文档
让我们从一个最简单的例子开始,创建一个包含基本元素的Word文档:
python复制from docx import Document
from docx.shared import Inches, Cm
# 1. 初始化文档
doc = Document() # 新建空白文档,不添加参数,默认新建
# 2. 添加段落
doc.add_paragraph("这是文档正文段落") # 直接添加段落
para = doc.add_paragraph("主段落") # 该方法返回新段落的引用对象
para.insert_paragraph_before("插入在主段落上方的段落") # 主段落的引用之前插入段落
# 3. 添加标题(级别1-9,0为文档标题)
doc.add_heading("文档总标题", level=0) # 一份报告的封面标题
doc.add_heading("第一章 概述", level=1) # 一级标题
doc.add_heading("1.1 核心功能", level=2) # 二级标题
# 4. 分页符
doc.add_page_break() # 强制后续内容另起一页
# 5. 保存文档
doc.save("基础文档示例.docx")
3.2 表格操作
表格是Word文档中非常重要的组成部分,python-docx提供了丰富的表格操作功能:
python复制# 5. 添加表格(固定行+动态行+样式)
# 5.1 固定表格(2行2列)
table1 = doc.add_table(rows=2, cols=2)
table1.cell(0, 0).text = "姓名"
table1.cell(0, 1).text = "年龄"
table1.cell(1, 0).text = "张三"
table1.cell(1, 1).text = "25"
# 5.2 动态表格(表头+数据行)
table2 = doc.add_table(rows=1, cols=3)
table2.style = "Light Shading Accent 1" # 应用预设样式
headers = ["数量", "产品编号", "描述"]
for i, header in enumerate(headers):
table2.rows[0].cells[i].text = header
# 批量添加数据
items = [(7, "1024", "毛绒小猫"), (3, "2042", "菲比精灵"), (1, "1288", "豪华项圈")]
for item in items:
row = table2.add_row().cells
row[0].text = str(item[0])
row[1].text = item[1]
row[2].text = item[2]
3.3 图片插入
在文档中添加图片也非常简单:
python复制# 6. 添加图片(本地文件+尺寸调整)
doc.add_picture("test.png", width=Inches(1.5)) # 1.5英寸宽(自动等比缩放)
doc.add_picture("test2.jpg", width=Cm(5), height=Cm(1)) # 同时指定宽高
3.4 列表和格式设置
python-docx支持各种列表和文本格式设置:
python复制# 7. 段落样式(项目符号/编号)
doc.add_paragraph("项目符号列表项1", style="ListBullet")
doc.add_paragraph("项目符号列表项2", style="ListBullet")
doc.add_paragraph("编号列表项1", style="ListNumber")
# 8. 字符格式(粗体/斜体)
para = doc.add_paragraph()
para.add_run("普通文本 ").bold = False
para.add_run("粗体文本").bold = True
para.add_run(" 普通文本 ").italic = False
para.add_run("斜体文本").italic = True
# 9. 字符样式(预设样式)
para2 = doc.add_paragraph("普通文本,")
para2.add_run("带强调的文本", style="Emphasis") # 应用"强调"样式
4. 高级文档操作技巧
4.1 文档节(Section)管理
Word文档可以包含多个节,每个节可以有不同的页面设置:
python复制from docx.enum.section import WD_SECTION_START, WD_ORIENT
# 1. 创建新文档并查看默认节
doc = Document()
print("初始文档的节数量:", len(doc.sections)) # 默认1个节
# 获取默认节并修改其基础布局
default_section = doc.sections[0]
default_section.left_margin = Inches(1.5)
default_section.right_margin = Inches(1)
default_section.top_margin = Inches(1)
default_section.bottom_margin = Inches(1)
# 2. 添加新节(奇数页开始,横向布局)
new_section = doc.add_section(WD_SECTION_START.ODD_PAGE)
new_section.orientation = WD_ORIENT.LANDSCAPE
new_width, new_height = new_section.page_height, new_section.page_width
new_section.page_width = new_width
new_section.page_height = new_height
# 3. 设置新节的边距
new_section.left_margin = Inches(1.25)
new_section.right_margin = Inches(1.25)
new_section.top_margin = Inches(0.8)
new_section.bottom_margin = Inches(0.8)
doc.save("多节文档示例.docx")
4.2 页眉页脚操作
页眉页脚是专业文档的重要组成部分:
python复制# 1. 初始化文档并创建基础页眉
doc = Document()
section = doc.sections[0]
header = section.header
# 为第一节添加简单页眉
para = header.paragraphs[0]
para.text = "文档主标题 - 第一节页眉"
# 2. 添加带分区(左/中/右)的页眉
para.clear()
para.text = "左侧:文档名称\t居中:2026年1月\t右侧:页码"
para.style = doc.styles["Header"] # 应用Word默认的"Header"样式
# 3. 添加页脚(包含页码)
footer = section.footer
footer_para = footer.paragraphs[0]
footer_para.text = "\t第 {PAGE} 页 / 共 {NUMPAGES} 页\t" # 居中显示页码
footer_para.style = doc.styles["Footer"]
doc.save("页眉页脚示例.docx")
4.3 样式管理
样式是Word文档格式化的核心:
python复制from docx.enum.style import WD_STYLE_TYPE
# 1. 创建新文档并访问样式集合
doc = Document()
styles = doc.styles
# 2. 创建自定义样式
citation_style = styles.add_style("Citation", WD_STYLE_TYPE.PARAGRAPH)
citation_style.base_style = styles["Normal"] # 继承Normal样式
# 设置字符格式
citation_style.font.name = "宋体"
citation_style.font.size = Pt(10)
citation_style.font.italic = True
citation_style.font.underline = True
# 设置段落格式
citation_style.paragraph_format.left_indent = Inches(0.25)
citation_style.paragraph_format.first_line_indent = Inches(-0.25)
citation_style.paragraph_format.space_before = Pt(6)
# 应用自定义样式
doc.add_paragraph("这是自定义Citation样式的引用文本", style="Citation")
doc.save("样式操作示例.docx")
5. 实战案例:自动化生成项目报告
让我们通过一个完整的案例,展示如何使用python-docx自动化生成一个专业的项目报告:
python复制from docx import Document
from docx.shared import Inches, Pt
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_project_report():
# 创建新文档
doc = Document()
# 设置文档默认字体(解决中文显示问题)
doc.styles['Normal'].font.name = '微软雅黑'
doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
# ========== 封面页 ==========
# 主标题
title = doc.add_heading('XX项目调研报告', 0)
title.alignment = WD_ALIGN_PARAGRAPH.CENTER
title_run = title.runs[0]
title_run.font.size = Pt(24)
title_run.font.bold = True
# 副标题
sub_para = doc.add_paragraph('报告生成时间:2026年1月\n报告编制人:自动化系统')
sub_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
for run in sub_para.runs:
run.font.size = Pt(14)
doc.add_page_break()
# ========== 目录页 ==========
doc.add_heading('目录', level=1)
# 实际项目中可以使用更复杂的方法生成目录
doc.add_paragraph('1. 项目概述 ................ 2')
doc.add_paragraph('2. 项目计划 ................ 3')
doc.add_paragraph('3. 风险评估 ................ 4')
doc.add_page_break()
# ========== 正文内容 ==========
# 1. 项目概述
doc.add_heading('1. 项目概述', level=1)
doc.add_paragraph('本项目旨在通过自动化技术提升办公效率,减少人工操作错误。')
# 项目目标表格
table = doc.add_table(rows=3, cols=2)
table.style = 'Table Grid'
table.cell(0, 0).text = '目标编号'
table.cell(0, 1).text = '目标描述'
table.cell(1, 0).text = 'OBJ-001'
table.cell(1, 1).text = '实现文档自动化生成'
table.cell(2, 0).text = 'OBJ-002'
table.cell(2, 1).text = '减少人工操作时间50%'
# 2. 项目计划
doc.add_heading('2. 项目计划', level=1)
doc.add_paragraph('项目计划分为以下三个阶段:')
doc.add_paragraph('• 需求分析阶段(1月-2月)', style='ListBullet')
doc.add_paragraph('• 开发实施阶段(3月-6月)', style='ListBullet')
doc.add_paragraph('• 测试验收阶段(7月)', style='ListBullet')
# 甘特图占位
doc.add_heading('2.1 项目甘特图', level=2)
doc.add_paragraph('此处应插入项目甘特图')
# 3. 风险评估
doc.add_heading('3. 风险评估', level=1)
risk_table = doc.add_table(rows=4, cols=3)
risk_table.style = 'Table Grid'
risk_table.cell(0, 0).text = '风险项'
risk_table.cell(0, 1).text = '可能性'
risk_table.cell(0, 2).text = '影响程度'
risk_table.cell(1, 0).text = '技术实现难度'
risk_table.cell(1, 1).text = '中'
risk_table.cell(1, 2).text = '高'
risk_table.cell(2, 0).text = '进度延迟'
risk_table.cell(2, 1).text = '低'
risk_table.cell(2, 2).text = '中'
risk_table.cell(3, 0).text = '预算超支'
risk_table.cell(3, 1).text = '低'
risk_table.cell(3, 2).text = '低'
# 保存文档
doc.save('自动化项目报告.docx')
generate_project_report()
6. 常见问题与解决方案
6.1 中文显示问题
当使用python-docx处理中文文档时,可能会遇到字体显示不正常的问题。解决方法是指定中文字体:
python复制from docx.oxml.ns import qn
# 设置文档默认字体
doc.styles['Normal'].font.name = '微软雅黑'
doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
# 对于特定段落
p = doc.add_paragraph()
run = p.add_run('中文内容')
run.font.name = '微软雅黑'
run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
6.2 表格合并单元格
合并单元格是表格操作中的常见需求:
python复制from docx import Document
doc = Document()
table = doc.add_table(rows=3, cols=3)
# 横向合并
cell_1_1 = table.cell(0, 0)
cell_1_2 = table.cell(0, 1)
cell_1_1.merge(cell_1_2)
cell_1_1.text = '合并的标题'
# 纵向合并
cell_2_3 = table.cell(1, 2)
cell_3_3 = table.cell(2, 2)
cell_2_3.merge(cell_3_3)
cell_2_3.text = '纵向合并'
doc.save('合并单元格示例.docx')
6.3 文档修改与批处理
python-docx不仅可以创建新文档,还可以修改现有文档:
python复制from docx import Document
# 打开现有文档
doc = Document('现有文档.docx')
# 修改所有段落
for para in doc.paragraphs:
if '旧文本' in para.text:
para.text = para.text.replace('旧文本', '新文本')
# 修改表格内容
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
if '旧数据' in cell.text:
cell.text = cell.text.replace('旧数据', '新数据')
# 保存修改后的文档
doc.save('修改后的文档.docx')
7. 性能优化与最佳实践
7.1 批量操作优化
当需要处理大量文档或大型文档时,性能优化很重要:
python复制# 不推荐的写法 - 频繁保存
for i in range(100):
doc = Document()
doc.add_paragraph(f"段落{i}")
doc.save(f"文档{i}.docx") # 每次循环都保存
# 推荐的写法 - 批量处理
docs = []
for i in range(100):
doc = Document()
doc.add_paragraph(f"段落{i}")
docs.append(doc)
# 最后统一保存
for i, doc in enumerate(docs):
doc.save(f"文档{i}.docx")
7.2 使用模板文档
对于格式复杂的文档,建议先创建好模板,然后通过python-docx填充内容:
- 先手动创建一个包含所有样式和格式的模板文档
- 使用python-docx打开模板并修改内容
python复制doc = Document('模板.docx') # 打开模板文档
# 找到模板中的特定段落并替换内容
for para in doc.paragraphs:
if '{项目名称}' in para.text:
para.text = para.text.replace('{项目名称}', '自动化办公系统')
doc.save('生成的项目文档.docx')
7.3 错误处理
健壮的程序应该包含适当的错误处理:
python复制from docx import Document
from docx.exceptions import PackageNotFoundError
try:
doc = Document('不存在的文件.docx')
except PackageNotFoundError:
print("文件不存在或不是有效的Word文档")
doc = Document() # 创建新文档作为后备
doc.add_paragraph("原始文档无法打开,这是新创建的内容")
try:
doc.save('/无权限的路径/文档.docx')
except PermissionError:
print("没有写入权限,将文档保存到临时目录")
doc.save('/tmp/文档.docx')
8. 扩展应用场景
8.1 邮件合并
python-docx可以轻松实现邮件合并功能:
python复制from docx import Document
# 模板文档
template = Document('邀请函模板.docx')
# 收件人数据
recipients = [
{'姓名': '张三', '职位': '技术总监', '公司': 'ABC科技'},
{'姓名': '李四', '职位': '产品经理', '公司': 'XYZ软件'}
]
# 为每个收件人生成文档
for person in recipients:
doc = Document('邀请函模板.docx')
# 替换模板中的占位符
for para in doc.paragraphs:
para.text = para.text.replace('{姓名}', person['姓名'])
para.text = para.text.replace('{职位}', person['职位'])
para.text = para.text.replace('{公司}', person['公司'])
# 保存个性化文档
doc.save(f"邀请函_{person['姓名']}.docx")
8.2 报告自动化
结合其他Python库,可以实现完整的报告自动化流程:
python复制import pandas as pd
from docx import Document
import matplotlib.pyplot as plt
# 从Excel读取数据
data = pd.read_excel('销售数据.xlsx')
# 生成图表
plt.figure(figsize=(8, 4))
data.groupby('月份')['销售额'].sum().plot(kind='bar')
plt.title('月度销售额')
plt.savefig('月度销售.png')
# 创建Word报告
doc = Document()
doc.add_heading('销售报告', 0)
# 添加摘要
doc.add_paragraph(f"总销售额: {data['销售额'].sum():,.2f}元")
doc.add_paragraph(f"平均每月销售额: {data.groupby('月份')['销售额'].sum().mean():,.2f}元")
# 添加表格
table = doc.add_table(rows=len(data)+1, cols=len(data.columns))
table.style = 'Table Grid'
# 表头
for j, col in enumerate(data.columns):
table.cell(0, j).text = str(col)
# 表格内容
for i, row in data.iterrows():
for j, value in enumerate(row):
table.cell(i+1, j).text = str(value)
# 添加图表
doc.add_picture('月度销售.png', width=Inches(6))
# 保存报告
doc.save('销售报告.docx')
8.3 文档比较与差异分析
虽然python-docx本身不提供文档比较功能,但可以结合其他工具实现:
python复制from docx import Document
import difflib
def compare_docs(doc1_path, doc2_path):
# 提取文档1文本
doc1 = Document(doc1_path)
text1 = '\n'.join([para.text for para in doc1.paragraphs])
# 提取文档2文本
doc2 = Document(doc2_path)
text2 = '\n'.join([para.text for para in doc2.paragraphs])
# 生成差异报告
diff = difflib.HtmlDiff().make_file(
text1.splitlines(),
text2.splitlines(),
fromdesc='文档1',
todesc='文档2'
)
# 保存差异报告
with open('差异报告.html', 'w', encoding='utf-8') as f:
f.write(diff)
compare_docs('旧版本.docx', '新版本.docx')
