python-docx是一款纯Python实现的第三方库,专门用于创建和修改Microsoft Word的.docx格式文档。该库无需依赖 Microsoft Word软件即可运行,具备优秀的跨平台特性,可在Windows、Mac、Linux等系统上使用。需要注意的是,python-docx仅兼容.docx 格式(对应 Word 2007 及以上版本),不支持旧版的.doc 格式文件。.docx是基于XML的开放压缩格式,而.doc是二进制私有格式,前者体积更小、兼容性更优。

python-docx官方代码仓库见: python-docx ,详细文档见: python-docx docs 。截至本文撰写时,python-docx的稳定版本为1.2.0,python-docx安装命令如下:

pip install python-docx

1 使用说明

1.1 快速入门

Python-docx中的Word文档内存对象模型采用树状结构分层映射文档元素,使得程序能够精准控制文档的内容、格式与布局。该树状结构示意如下:

Document(文档)
├── Sections(节)
├── Paragraphs(段落)
│   ├── Runs(文本片段)
│   └── InlineShapes(内联形状,如图片)
├── Tables(表格)
│   ├── Rows(行)
│   │   └── Cells(单元格)
│   │       └── Paragraphs(单元格内的段落)
└── Core Properties(文档属性)

各个对象简介如下:

在文档树中的位置 主要功能与说明

以下代码示例描述了如何通过python-docx库快速实现文档的创建,完成段落、标题、表格、图片等内容添加及字符段落样式设置,并保存为docx文件:

# 1. 初始化文档
from docx import Document
from docx.shared import Inches, Cm
# 新建空白文档,不添加参数,默认新建
doc = Document()  
# 2. 添加段落
# 默认都会把内容追加到文档的末尾
doc.add_paragraph("这是文档正文段落")  # 直接添加段落
para = doc.add_paragraph("主段落") # 该方法返回新段落的引用对象
para.insert_paragraph_before("插入在主段落上方的段落")  # 主段落的引用之前插入段落
para = doc.add_paragraph("插入在主段落下方的段落") # 主段落的引用之后插入段落
# 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. 添加表格(固定行+动态行+样式)
# 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)
# 将鼠标悬停在Word表格样式库中的表格样式缩略图上,即可找到表格样式名称
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]
# 6. 添加图片(本地文件+尺寸调整)
doc.add_picture("test.png", width=Inches(1.5))  # 1.5英寸宽(自动等比缩放)
doc.add_picture("test2.jpg", width=Cm(5),height=Cm(1))  # 同时指定宽高
# 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")  # 应用"强调"样式
# 10. 保存文档
doc.save("test_output.docx")

后续内容将对python-docx的各个核心对象进行具体介绍。

1.2 Python-docx的核心对象

1.2.1 Document对象

Python-docx本质上是一个文档修改工具。即使创建新文档,其原理也是基于一个预设的空白模板进行修改。因此,文档的格式(如样式、页眉、页脚)与正文内容是分离存储的,即使清空模板文字也不会删除格式设定。以下示例展示了如何创建文档或打开已有文档:

from docx import Document
from io import BytesIO, StringIO  # 用于类文件对象操作
"""演示python-docx操作文档的核心功能"""
# ===================== 1. 创建新文档并保存 =====================
print("1. 创建新文档并保存...")
# 基于默认模板创建空文档
new_doc = Document()
new_doc.add_heading('python-docx 文档操作示例', level=1)
new_doc.add_paragraph('这是通过python-docx创建的新文档')
# 保存新文档到本地
new_doc.save('新建文档.docx')
print("✅ 新文档已保存为:新建文档.docx")
# ===================== 2. 打开现有文档并修改保存 =====================
print("\n2. 打开现有文档并修改...")
# 打开刚才创建的文档
existing_doc = Document('新建文档.docx')
# 向文档追加内容
existing_doc.add_paragraph('这是打开现有文档后追加的内容')
# 另存为新文件(避免覆盖原文件)
existing_doc.save('修改后的文档.docx')
print("✅ 修改后的文档已保存为:修改后的文档.docx")
# ===================== 3. 通过类文件对象(BytesIO)读写文档 =====================
print("\n3. 通过类文件对象操作文档...")
# 3.1 读取:将本地文档读取到BytesIO流中
with open('修改后的文档.docx', 'rb') as f:  # 必须用rb(二进制读),跨平台兼容
    doc_stream = BytesIO(f.read())  # 用BytesIO而非StringIO
# 从流中打开文档
stream_doc = Document(doc_stream)
# 追加内容
stream_doc.add_paragraph('这是通过类文件对象添加的内容')
# 3.2 保存:将文档保存到BytesIO流中(不落地到本地文件)
output_stream = BytesIO()
stream_doc.save(output_stream)
# 可选:将流中的内容写入本地文件,验证结果
with open('类文件对象生成的文档.docx', 'wb') as f:
    f.write(output_stream.getvalue())
print("✅ 类文件对象操作的文档已保存为:类文件对象生成的文档.docx")
# 关闭流
doc_stream.close()
output_stream.close()

1.2.2 Table对象

Word软件中的表格功能相当复杂,这导致在使用python-docx操作表格时,往往难以提前明确表格的具体内容和结构,增加了处理的难度。本节将从简单表格到复杂表格来介绍如何使用python-docx操作表格。

规整表格也就是一个行列数固定、无合并或省略单元格的标准表格,这是最基础的表格形式。关系型数据库表和pandas数据表都是规整表格的典型示例:

+---+---+---+
| a | b | c |
+---+---+---+
| d | e | f |
+---+---+---+
| g | h | i |
+---+---+---+

通过控制表格行列数即可创建规整表格:

from docx import Document
from docx.shared import Inches
# 创建新文档
doc = Document()
# 添加3行2列的规整表格
table = doc.add_table(rows=3, cols=2)
table.style = 'Table Grid'  # 显示表格边框,便于查看
# 填充单元格内容(a-i 对应示例中的规整表格)
cell_texts = ['a', 'b', 'c', 'd', 'e', 'f']
idx = 0
for row in table.rows:
    for cell in row.cells:
        cell.text = cell_texts[idx]
        idx += 1
# 保存文档
doc.save('规整表格示例.docx')
# 读取并验证规整表格的行列数(每行单元格数相同)
print("规整表格每行的单元格数:")
for i, row in enumerate(table.rows):
    print(f"第{i+1}行:{len(row.cells)}个单元格")

合并单元格

将多个连续的横向或纵向单元格合并为一个单元格,是实际使用中非常常见的方式:

+---+---+---+   +---+---+---+
|   a   | b |   |   | b | c |
+---+---+---+   + a +---+---+
| c | d | e |   |   | d | e |
+---+---+---+   +---+---+---+
| f | g | h |   | f | g | h |
+---+---+---+   +---+---+---+

实现方式为先创建规整表格,再通过cell.merge()实现单元格的横向或纵向合并:

from docx import Document
doc = Document()
table = doc.add_table(rows=2, cols=3)
table.style = 'Table Grid'
# 示例1:横向合并(第一行第一个单元格合并右侧单元格)
cell_1_1 = table.cell(0, 0)  # 第1行第1列(索引从0开始)
cell_1_2 = table.cell(0, 1)
cell_1_1.merge(cell_1_2)
cell_1_1.text = '合并单元格(横向)'
# 示例2:纵向合并(第三列前两个单元格合并)
cell_1_3 = table.cell(0, 2)
cell_2_3 = table.cell(1, 2)
cell_1_3.merge(cell_2_3)
cell_1_3.text = '合并单元格(纵向)'
# 填充其他单元格
table.cell(1, 0).text = 'd'
table.cell(1, 1).text = 'e'
# 查看合并后每行的单元格数
# 注意以下内容返回的是原始表格结构
print("合并单元格后每行的单元格数:")
for i, row in enumerate(table.rows):
    print(f"第{i+1}行:{len(row.cells)}个单元格")
doc.save('合并单元格示例.docx')

表格处理的另一个复杂点是其递归特性,Word中的表格单元格本身可以包含一个或多个表格。可以通过_Cell.tables_Cell.iter_inner_content()检测嵌套表格:

  • _Cell.tables:直接返回单元格内包含的所有表格。
  • _Cell.iter_inner_content():按文档顺序返回单元格内的所有内容(包括段落和表格),保持表格与段落的相对位置不变。
  • 示例代码如下:

    from docx import Document
    from docx.shared import Inches
    from docx.table import Table
    from docx.text.paragraph import Paragraph
    def generate_nested_table_doc():
        """生成带嵌套表格的示例Word文档(示例数据)"""
        # 1. 创建新文档
        doc = Document()
        # 2. 创建外层表格(2行2列)
        outer_table = doc.add_table(rows=2, cols=2)
        outer_table.style = 'Table Grid'  # 显示表格边框
        # 3. 填充外层表格的普通单元格
        cell_1_1 = outer_table.cell(0, 0)
        cell_1_1.text = "下方单元格包含嵌套表格"
        cell_1_2 = outer_table.cell(0, 1)
        cell_1_2.text = "普通单元格(无嵌套)"
        # 4. 关键:在 (1,0) 单元格中嵌套一个子表格
        cell_2_1 = outer_table.cell(1, 0)
        # 先给嵌套表格前加一个段落(模拟真实文档的混合内容)
        para = cell_2_1.add_paragraph("嵌套表格前的段落内容:")
        # 在单元格内创建嵌套表格(3行1列)
        inner_table = cell_2_1.add_table(rows=3, cols=1)
        inner_table.style = 'Table Grid'
        # 填充嵌套表格
        inner_table.cell(0, 0).text = "嵌套表格-行1"
        inner_table.cell(1, 0).text = "嵌套表格-行2"
        inner_table.cell(2, 0).text = "嵌套表格-行3"
        # 嵌套表格后再加一个段落
        cell_2_1.add_paragraph("嵌套表格后的段落内容")
        # 5. 填充外层表格最后一个单元格
        cell_2_2 = outer_table.cell(1, 1)
        cell_2_2.text = "普通单元格(无嵌套)"
        # 6. 保存文档(生成示例数据)
        doc.save("嵌套表格.docx")
        print("=" * 50)
        print("✅ 嵌套表格.docx")
        print("=" * 50)
    def traverse_table(table, level=0):
        递归遍历表格,处理嵌套表格
        :param table: 要遍历的表格对象
        :param level: 表格嵌套层级(外层为0,内层+1)
        indent = "  " * level  # 缩进,方便区分层级
        print(f"\n{indent}=== 遍历【层级{level}】表格 ===")
        # 遍历表格的每一行
        for row_idx, row in enumerate(table.rows):
            # 遍历行中的每一个单元格
            for col_idx, cell in enumerate(row.cells):
                print(f"\n{indent}单元格 ({row_idx+1}, {col_idx+1}):")
                # --------------------------
                # 方法1:_Cell.tables - 直接获取单元格内的所有表格
                # --------------------------
                inner_tables = cell.tables
                if inner_tables:
                    print(f"{indent}  📌 检测到 {len(inner_tables)} 个嵌套表格:")
                    # 递归遍历每个嵌套表格
                    for inner_table in inner_tables:
                        traverse_table(inner_table, level + 1)
                else:
                    print(f"{indent}  📌 无嵌套表格")
                # --------------------------
                # 方法2:_Cell.iter_inner_content() - 按顺序获取单元格内所有内容(段落+表格)
                # --------------------------
                print(f"{indent}  📌 单元格内完整内容(按顺序):")
                for content in cell.iter_inner_content():
                    if isinstance(content, Paragraph):
                        # 处理段落内容(过滤空段落)
                        text = content.text.strip()
                        if text:
                            print(f"{indent} [段落]:{text}")
                    elif isinstance(content, Table):
                        # 遇到表格时的提示(避免重复遍历,仅演示位置)
                        print(f"{indent} [表格]:嵌套表格(层级{level+1})")
    def parse_nested_tables():
        """解析生成的嵌套表格文档,演示核心方法"""
        # 1. 打开示例文档
        doc = Document("嵌套表格.docx")
        # 2. 遍历文档中的所有外层表格
        print("\n开始解析嵌套表格:")
        print("-" * 50)
        for table in doc.tables:
            traverse_table(table)
    # 主程序入口
    if __name__ == "__main__":
        # 生成带嵌套表格的示例文档
        generate_nested_table_doc()
        # 第二步:解析嵌套表格,演示_Cell.tables和iter_inner_content的使用
        parse_nested_tables()
        print("\n" + "=" * 50)
        print("✅ 嵌套表格解析完成!")
        print("=" * 50)
    

    1.2.3 文本处理

    在Word文档中,内容的组织逻辑分为两个主要层级:块级对象和行内对象。

  • 块级对象(如段落、表格)是占据整行的大模块,其宽度由页面边距、分栏或单元格边界决定,文本会在其左右边界内自动换行。
  • 行内对象则存在于这些大模块内部,如加粗的词语或句子,最常见的表现形式是文本片段(runs)。一个段落就是由一个或多个文本片段组成的。
  • 相应地,格式控制也分为两类:

  • 块级属性(如缩进、间距、对齐方式)控制模块在页面上的布局位置;
  • 行内属性(如字体、加粗、颜色)则控制模块内部文字的具体外观。
  • 下面通过Python-docx的代码示例,展示这两类格式的实际应用:

    from docx import Document
    from docx.shared import Inches, Pt, RGBColor
    from docx.enum.text import (
        WD_ALIGN_PARAGRAPH,
        WD_TAB_ALIGNMENT,
        WD_TAB_LEADER,
        WD_UNDERLINE
    from docx.enum.dml import MSO_THEME_COLOR
    # 创建一个新的 Word 文档
    doc = Document()
    # ==================== 1. 块级格式设置:段落布局控制 ====================
    # 1.1 标题段落(居中对齐、段后间距)
    title_para = doc.add_paragraph("Python-docx 文本格式示例")
    title_format = title_para.paragraph_format  # 块级格式对象
    title_format.alignment = WD_ALIGN_PARAGRAPH.CENTER  # 居中对齐(块级属性)
    title_format.space_after = Pt(18)  # 段后间距(块级属性)
    # 1.2 正文段落(缩进与行间距)
    content_para = doc.add_paragraph("这是一个带缩进和自定义行间距的正文段落。")
    content_format = content_para.paragraph_format
    content_format.left_indent = Inches(0.5)          # 左缩进
    content_format.first_line_indent = Inches(-0.25)  # 悬挂缩进
    content_format.line_spacing = 1.5                # 1.5倍行间距
    content_format.space_before = Pt(12)             # 段前间距
    # 1.3 带制表位的段落(块级定位)
    tab_para = doc.add_paragraph("姓名:\t张三\t年龄:\t25")
    tab_format = tab_para.paragraph_format
    tab_stops = tab_format.tab_stops
    # 添加三个制表位(位置、对齐方式、前导符)
    tab_stops.add_tab_stop(Inches(1.5), WD_TAB_ALIGNMENT.RIGHT, WD_TAB_LEADER.DOTS)
    tab_stops.add_tab_stop(Inches(2.5), WD_TAB_ALIGNMENT.LEFT, WD_TAB_LEADER.SPACES)
    tab_stops.add_tab_stop(Inches(3.5), WD_TAB_ALIGNMENT.RIGHT, WD_TAB_LEADER.DOTS)
    # 1.4 分页控制(块级保持与孤行控制)
    page_para1 = doc.add_paragraph("这是章节标题(确保与下一段同页)")
    page_para1.paragraph_format.keep_with_next = True  # 与下段同页
    page_para2 = doc.add_paragraph("这是章节内容,启用了孤行控制,避免段落首行/末行单独显示在一页。" * 20)
    page_para2.paragraph_format.widow_control = True   # 避免孤行
    # ==================== 2. 行内格式设置:文字外观控制 ====================
    char_para = doc.add_paragraph("字符格式示例:")
    bold_run = char_para.add_run("粗体文本")
    bold_run.font.bold = True
    char_para.add_run(" | ")
    italic_run = char_para.add_run("斜体文本")
    italic_run.font.italic = True
    char_para.add_run(" | ")
    # 下划线(双下划线)
    underline_run = char_para.add_run("双下划线文本")
    underline_run.font.underline = WD_UNDERLINE.DOUBLE
    char_para.add_run(" | ")
    # 不同字号和颜色
    color_run = char_para.add_run("16号红色文本")
    color_run.font.size = Pt(16)               # 字号
    color_run.font.color.rgb = RGBColor(255, 0, 0)  # 颜色
    char_para.add_run(" | ")
    sup_run = char_para.add_run("上标")
    sup_run.font.superscript = True
    # ==================== 3. 保存文档 ====================
    doc.save("文本格式示例.docx")
    print("文档已保存为:文本格式示例.docx")
    

    1.2.4 Sections对象

    Word引入了节(section)的概念,它指文档中具有相同页面布局(如页边距、纸张方向)的连续部分。通过分节,用户可以在同一份文档中混合使用不同版式,例如同时包含纵向页面和横向页面。此外,每个节还可以独立设置其页眉与页脚的样式。绝大多数Word文档默认仅包含一个节,通常也无需更改页面布局。然而,当确实需要对页面布局进行调整时,理解节的功能与设置方法就变得至关重要。以下示例展示了如何使用python-docx库创建包含多个节、各节拥有不同页面设置的Word文档:

    from docx import Document
    from docx.enum.section import WD_SECTION_START
    from docx.enum.section import WD_ORIENT
    from docx.shared import Inches
    # 1. 创建新文档并查看默认节
    document = Document()
    print("初始文档的节数量:", len(document.sections))  # 默认1个节
    # 获取默认节并修改其基础布局(纵向,常规边距)
    default_section = document.sections[0]
    # 设置默认节的边距:左1.5英寸、右1英寸、上下各1英寸
    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. 给默认节添加内容(纵向页面内容)
    document.add_heading('第一节:纵向页面内容', level=1)
    document.add_paragraph('这是默认节的内容,页面为纵向,边距:左1.5英寸、右1英寸。')
    # 3. 添加新节(奇数页开始,横向布局)
    # 创建新节,指定分节符类型为奇数页开始
    new_section = document.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
    # 设置新节的边距:左右各1.25英寸,上下各0.8英寸
    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)
    # 4. 给新节添加内容(横向页面内容)
    document.add_heading('第二节:横向页面内容', level=1)
    document.add_paragraph('这是新节的内容,页面为横向,边距:左右1.25英寸、上下0.8英寸。')
    # 5. 再添加一个新节(偶数页开始,纵向布局)
    third_section = document.add_section(WD_SECTION_START.EVEN_PAGE)
    # 恢复纵向布局
    third_section.orientation = WD_ORIENT.PORTRAIT
    third_section.page_width = Inches(8.5)
    third_section.page_height = Inches(11)
    # 设置特殊边距(添加装订线)
    third_section.gutter = Inches(0.2)  # 装订线0.2英寸
    third_section.header_distance = Inches(0.6)  # 页眉距离0.6英寸
    # 6. 给第三个节添加内容
    document.add_heading('第三节:带装订线的纵向页面', level=1)
    document.add_paragraph('这一节包含0.2英寸的装订线,页眉距离页面顶部0.6英寸。')
    # 7. 遍历所有节,打印关键属性
    print("\n=== 所有节的关键属性 ===")
    for idx, section in enumerate(document.sections):
        print(f"\n第{idx+1}节:")
        print(f"  起始类型:{section.start_type}")
        print(f"  页面方向:{section.orientation}")
        print(f"  左右边距:{section.left_margin/914400:.2f}英寸 / {section.right_margin/914400:.2f}英寸")
        print(f"  装订线:{section.gutter/914400:.2f}英寸")
    # 保存文档
    document.save("多节文档示例.docx")
    print("\n文档已保存为:多节文档示例.docx")
    

    1.2.5 页眉页脚对象

    页眉是指显示在每一页上页边距区域的文本,与正文内容相互独立,通常用于展示文档标题、作者、创建日期或页码等上下文信息。同一文档中的页眉在各页面间基本保持一致,仅在部分内容上可能存在细微差异,例如章节标题或页码的变化。页脚在功能和特性上与页眉完全类似,唯一的区别是页脚位于页面底部。页脚与脚注不同,脚注在各页面间并不统一。以下是操作文档页眉页脚的示例代码:

    from docx import Document
    # -------------------------- 1. 初始化文档并创建基础页眉 --------------------------
    # 创建新文档
    doc = Document()
    # 获取文档的第一个节(新建文档默认只有1个节)
    section1 = doc.sections[0]
    header1 = section1.header
    # 检查初始状态:新建文档的页眉默认关联到前一节页眉设置(此处无前置节,故无实际页眉)
    print(f"初始页眉关联状态: {header1.is_linked_to_previous}")  # 输出: True
    # 为第一节添加简单页眉(仅左侧文本)
    # 直接编辑页眉的第一个段落(新建页眉默认包含1个空段落)
    para1 = header1.paragraphs[0]
    para1.text = "文档主标题 - 第一节页眉"
    # 自动创建独立页眉定义,关联状态变为False
    print(f"添加页眉后关联状态: {header1.is_linked_to_previous}")  # 输出: False
    # -------------------------- 2. 添加带分区(左/中/右)的页眉 --------------------------
    # 先清空第一节原有页眉内容,重新设置分区页眉
    para1.clear()
    # 使用制表符\t分隔左、中、右三部分内容
    para1.text = "左侧:文档名称\t居中:2026年1月\t右侧:页码"
    # 应用Word默认的"Header"样式(确保制表位生效)
    para1.style = doc.styles["Header"]
    # -------------------------- 3. 添加新节并设置独立页眉 --------------------------
    # 向文档末尾添加新节(section2)
    section2 = doc.add_section()
    header2 = section2.header
    # 初始状态:新节的页眉默认关联到前一节(section1)
    print(f"第二节初始关联状态: {header2.is_linked_to_previous}")  # 输出: True
    # 验证:此时编辑header2的内容会直接修改section1的页眉(继承特性)
    # 先取消关联,创建第二节的独立页眉
    header2.is_linked_to_previous = False
    # 为第二节添加专属页眉
    para2 = header2.paragraphs[0]
    para2.text = "第二节独立页眉 - 仅本节显示"
    # -------------------------- 4. 添加页脚(与页眉用法完全一致) --------------------------
    # 为第一节添加页脚(包含页码)
    footer1 = doc.sections[0].footer
    footer1.is_linked_to_previous = False  # 取消关联,创建独立页脚
    footer_para1 = footer1.paragraphs[0]
    footer_para1.text = "\t第 {PAGE} 页 / 共 {NUMPAGES} 页\t"  # 居中显示页码
    footer_para1.style = doc.styles["Footer"]
    # 为第二节添加不同的页脚
    footer2 = doc.sections[1].footer
    footer2.is_linked_to_previous = False
    footer_para2 = footer2.paragraphs[0]
    footer_para2.text = "第二节页脚 - 联系人:测试账号"
    # -------------------------- 5. 删除页眉(恢复关联状态) --------------------------
    # 若需删除第二节的独立页眉,只需将其关联状态设为True(会永久删除内容)
    # 此处仅演示,注释掉避免影响最终效果
    # header2.is_linked_to_previous = True
    # -------------------------- 6. 保存文档 --------------------------
    doc.save("页眉页脚示例.docx")
    print("文档已保存为:页眉页脚示例.docx")
    

    1.3 非文本内容管理

    1.3.1 样式管理

    在Word中,内置样式会出现在Word界面的样式面板中,但不会自动加入文档中,直到你第一次使用它。这样避免了文件因所有样式定义而臃肿。一旦某样式被使用,其定义就会永久加入文档,即使后来删除应用内容也不会消失。因此,若要用python-docx使样式生效,必须在初始文档中包含其定义,否则样式会静默失效。
    以下是一个综合性的示例,它整合了文档中所有核心的样式操作功能,包括样式的访问、应用、创建、删除,以及字符段落格式的定义等:

    from docx import Document
    from docx.enum.style import WD_STYLE_TYPE
    from docx.shared import Pt, Inches
    from docx.enum.text import WD_UNDERLINE
    # 1. 创建新文档并访问样式集合
    doc = Document()
    styles = doc.styles
    print(f"初始样式数量: {len(styles)}")
    # 2. 访问并筛选特定类型的样式
    # 筛选所有段落样式并打印名称
    print("\n=== 所有段落样式 ===")
    paragraph_styles = [s for s in styles if s.type == WD_STYLE_TYPE.PARAGRAPH]
    for style in paragraph_styles[:5]:  # 只打印前5个避免输出过长
        print(f"- {style.name}")
    # 3. 应用现有样式到新段落
    # 方式1: 创建时指定样式名称
    doc.add_heading("样式操作示例", level=0)
    heading1_para = doc.add_paragraph("这是应用 Heading 1 样式的段落", style="Heading 1")
    # 方式2: 先创建段落再赋值样式对象
    normal_para = doc.add_paragraph()
    normal_para.text = "这是先创建再应用 Normal 样式的段落"
    normal_para.style = styles["Normal"]
    # 4. 创建自定义样式
    # 4.1 创建段落样式并设置基础样式、字符格式、段落格式
    citation_style = styles.add_style("Citation", WD_STYLE_TYPE.PARAGRAPH)
    # 设置基础样式(继承 Normal 样式的格式)
    citation_style.base_style = styles["Normal"]
    # 设置字符格式
    citation_style.font.name = "宋体"
    citation_style.font.size = Pt(10)
    citation_style.font.italic = True  # 斜体
    citation_style.font.underline = WD_UNDERLINE.DOT_DASH  # 点划线下划线
    # 设置段落格式(悬挂缩进、段前间距)
    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)
    # 设置后续段落样式
    citation_style.next_paragraph_style = styles["Normal"]
    # 应用自定义样式
    citation_para = doc.add_paragraph("这是自定义 Citation 样式的引用文本", style="Citation")
    print(f"\n自定义样式应用后名称: {citation_para.style.name}")
    # 5. 控制样式在 Word 中的显示(快速样式、优先级)
    body_text_style = styles["Body Text"]
    body_text_style.hidden = False
    body_text_style.quick_style = True
    body_text_style.priority = 1
    # 6. 处理潜在样式(Latent Styles)
    latent_styles = styles.latent_styles
    print(f"\n潜在样式总数: {len(latent_styles)}")
    # 为 List Bullet 添加潜在样式定义
    if "List Bullet" not in latent_styles:
        latent_list_bullet = latent_styles.add_latent_style("List Bullet")
        latent_list_bullet.hidden = False
        latent_list_bullet.priority = 2
        latent_list_bullet.quick_style = True
    print(f"List Bullet 潜在样式优先级: {latent_styles['List Bullet'].priority}")
    # 7. 删除样式
    print(f"\n删除前样式数量: {len(styles)}")
    if "Citation" in styles:
        styles["Citation"].delete()
        print(f"删除后样式数量: {len(styles)}")
    # 8. 保存文档
    doc.save("样式操作示例.docx")
    print("\n文档已保存为: 样式操作示例.docx")
    

    1.3.2 批注管理

    Word支持在文档中添加批注,这是审阅功能的一部分,通常用于他人在不修改原文的情况下提供反馈。Word文档里操作步骤如下:

  • 选取文本范围;
  • 点击审阅工具栏中的新建批注;
  • 输入或粘贴批注内容。
  • 批注仅能添加至文档主体,不可插入页眉、页脚或其他批注内。Word文档里脚注和尾注中理论上允许添加批注,但当前python-docx暂不支持该操作。此外高版本Word支持解决批注和回复批注功能,但python-docx暂未实现。以下是包含批注创建、富文本批注、元数据修改及批注遍历的完整示例:

    # 导入必要的库
    from docx import Document
    from datetime import datetime, timezone
    创建文档并演示批注的完整操作流程:
    1. 创建基础批注
    2. 创建富文本格式批注
    3. 修改批注元数据
    4. 访问和遍历所有批注
    # 1. 初始化文档对象
    doc = Document()
    doc.add_heading("Python-docx 批注演示文档", level=1)
    # 2. 示例1:创建基础文本批注
    para1 = doc.add_paragraph("这是第一段测试文本,用于添加基础批注。")
    # 为整段文本添加基础批注
    basic_comment = doc.add_comment(
        runs=para1.runs,  # 关联的文本块
        text="基础批注:这段文本表述清晰,建议保留。",  # 批注纯文本内容
        author="张三",  # 批注作者
        initials="ZS"  # 作者缩写
    print(f"✅ 基础批注创建完成")
    # 3. 示例2:创建富文本格式批注(包含粗体、斜体等样式)
    para2 = doc.add_paragraph("这是第二段测试文本,用于添加富文本批注。")
    # 创建空内容批注(后续手动添加富文本)
    rich_comment = doc.add_comment(
        runs=para2.runs,
        text="",  # 初始为空,后续添加富文本
        author="李四",
        initials="LS"
    # 向批注中添加富文本内容
    cmt_para = rich_comment.paragraphs[0]  # 获取批注的默认段落
    cmt_para.add_run("富文本批注:")  # 普通文本
    cmt_para.add_run("重点建议:").bold = True  # 粗体文本
    cmt_para.add_run("这段文本需要补充案例,").italic = True  # 斜体文本
    cmt_para.add_run("建议参考行业标准。")  # 普通文本
    # 4. 示例3:修改批注元数据(作者、缩写)
    basic_comment.author = "张小三"  # 修改作者名
    basic_comment.initials = "ZXS"  # 修改作者缩写
    print(f"✅ 基础批注元数据已更新:作者={basic_comment.author},缩写={basic_comment.initials}")
    # 5. 示例4:访问和遍历所有批注
    print("\n📋 文档中所有批注信息:")
    for idx, comment in enumerate(doc.comments):
        print(f"\n批注 {idx+1}:")
        print(f"  作者:{comment.author}")
        print(f"  缩写:{comment.initials}")
        # 提取批注的完整文本(兼容富文本)
        comment_text = "\n  ".join([para.text for para in comment.paragraphs])
        print(f"  内容:{comment_text}")
    # 6. 保存文档
    doc.save("批注演示文档.docx")
    print("\n📄 文档已保存为:批注演示文档.docx")
    

    1.3.3 图片对象

    Word文档中的内容分为两个图层:文本层和绘图层。文本层按从左到右、自上而下的顺序排列,页满则自动换页。绘图层中的对象称为形状,可自由放置。图片是一种特殊形状,可置于文本层或绘图层。位于文本层的图片称为嵌入式图片,它在排版中被视为一个大型文本字符:行高会自动调整以容纳图片,并支持类似文本的换行效果。若在其前方插入文本,图片会随之向后移动。嵌入式图片通常独占一个段落,但也可与前后文本共存于同一段落中。

    当前python-docx库仅支持嵌入式图片。通过Document.add_picture()方法可将图片默认添加至文档末尾的独立段落中,但经过适当设置,也能实现灵活的图文混排效果,示例如下:

    from docx import Document
    from docx.shared import Inches, Pt
    from docx.enum.text import WD_ALIGN_PARAGRAPH
    # 1. 创建一个新的Word文档
    doc = Document()
    # 2. 基础用法:在文档末尾插入图片(单独占一个段落)
    doc.add_heading('1. 基础插入图片', level=2)
    # 添加图片,设置宽度为2英寸(高度会按比例自动调整)
    doc.add_picture('test.png', width=Inches(2))
    # 3. 进阶用法:图文混排(图片和文本在同一个段落)
    doc.add_heading('2. 图文混排示例', level=2)
    # 创建一个新段落
    mixed_paragraph = doc.add_paragraph()
    # 添加文本到段落开头
    mixed_paragraph.add_run('这是图片左侧的文本,')
    # 在段落中插入图片(非单独段落)
    img_run = mixed_paragraph.add_run()
    img_run.add_picture('test.png', width=Inches(1))
    # 在图片右侧添加文本
    mixed_paragraph.add_run('这是图片右侧的文本。')
    # 4. 自定义图片尺寸+段落对齐
    doc.add_heading('3. 自定义尺寸与对齐', level=2)
    align_para = doc.add_paragraph()
    align_para.alignment = WD_ALIGN_PARAGRAPH.CENTER  # 段落居中对齐
    align_run = align_para.add_run()
    # 同时设置宽度和高度(注意:可能导致图片变形)
    align_run.add_picture('test.png', width=Inches(1.5), height=Inches(1))
    align_para.add_run('\n这是居中显示的图片')
    # 5. 保存文档
    doc.save('形状图片示例.docx')
    print("文档已保存为形状图片示例.docx")
    

    1.4 综合示例

    在实际应用中,python-docx主要被用于文档修改和自动化生成,而非从头创建文档。本节将通过一个综合示例,展示如何对一个包含标题、段落、多种表格、多张图片和分页符的多页文档进行针对性修改,并提供相应的文档生成代码。

    以下代码生成一个示例多页文档,涵盖了日常办公中常见的文档结构:

    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 ensure_test_images():
        # 简单生成测试图片(如果没有的话)
            from PIL import Image
            for i in range(1, 3):
                img_path = f"image{i}.jpg"
                if not os.path.exists(img_path):
                    img = Image.new('RGB', (800, 600), color='lightblue')
                    img.save(img_path)
            print("测试图片已准备完成")
        except ImportError:
            print("请安装pillow库:pip install pillow")
            exit(1)
    # 生成Word文档
    def generate_complex_doc():
        # 创建新文档
        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月  报告编制人:测试用户')
        sub_para.alignment = WD_ALIGN_PARAGRAPH.RIGHT
        sub_para_run = sub_para.runs[0]
        sub_para_run.font.size = Pt(10)
        # 正文段落
        doc.add_heading('一、项目概述', level=1)
        overview_para = doc.add_paragraph()
        overview_para.add_run('本项目针对企业数字化转型需求,重点解决现有业务系统数据孤岛、流程不规范、决策效率低等核心问题。').font.size = Pt(12)
        overview_para.add_run('\n项目覆盖范围包括:').font.bold = True
        overview_para.add_run('\n1) 生产管理模块:实现生产流程自动化监控')
        overview_para.add_run('\n2) 销售管理模块:打通客户数据与订单系统')
        overview_para.add_run('\n3) 财务管理模块:实现财务数据实时汇总分析')
        # 第一个表格:项目基础信息表(2行4列)
        doc.add_heading('1.1 项目基础信息', level=2)
        table1 = doc.add_table(rows=2, cols=4)
        table1.alignment = WD_TABLE_ALIGNMENT.CENTER  # 表格居中
        table1.style = 'Table Grid'  # 带边框样式
        # 填充表格1表头
        hdr_cells = table1.rows[0].cells
        hdr_cells[0].text = '项目编号'
        hdr_cells[1].text = '项目名称'
        hdr_cells[2].text = '启动时间'
        hdr_cells[3].text = '预计工期'
        # 填充表格1内容
        row_cells = table1.rows[1].cells
        row_cells[0].text = 'XM2026001'
        row_cells[1].text = '企业数字化转型项目'
        row_cells[2].text = '2026-01-01'
        row_cells[3].text = '12个月'
        # 调整表格1单元格字体
        for row in table1.rows:
            for cell in row.cells:
                for paragraph in cell.paragraphs:
                    for run in paragraph.runs:
                        run.font.size = Pt(10)
                        run.font.name = '微软雅黑'
                        run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
        # 插入第一张图片
        doc.add_heading('1.2 项目架构图', level=2)
        img1_para = doc.add_paragraph()
        img1_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
        img1_run = img1_para.add_run()
        img1_run.add_picture('image1.jpg', width=Inches(5))  # 图片宽度5英寸
        img1_para.add_run('\n图1:项目整体架构图').font.size = Pt(10)
        # 插入分页符(第一页结束)
        doc.add_page_break()
        # ========== 第二页内容 ==========
        doc.add_heading('二、项目资源配置', level=1)
        resource_para = doc.add_paragraph('本项目所需资源包括人力资源、硬件资源、软件资源三大类,具体配置如下表所示:')
        # 第二个表格:资源配置表(5行3列)
        table2 = doc.add_table(rows=5, cols=3)
        table2.style = 'Table Grid'
        table2.alignment = WD_TABLE_ALIGNMENT.CENTER
        # 填充表格2
        table2_data = [
            ['资源类型', '规格/数量', '备注'],
            ['人力资源', '项目经理1人,开发工程师5人,测试工程师2人', '均为全职'],
            ['服务器', '8核16G云服务器3台', '阿里云ECS'],
            ['数据库', 'MySQL 8.0 主从架构', '数据实时备份'],
            ['软件授权', 'Python、Office、开发工具', '企业版授权']
        for i, row_data in enumerate(table2_data):
            row_cells = table2.rows[i].cells
            for j, cell_text in enumerate(row_data):
                row_cells[j].text = cell_text
                # 设置单元格字体
                for paragraph in row_cells[j].paragraphs:
                    for run in paragraph.runs:
                        run.font.size = Pt(10)
                        run.font.name = '微软雅黑'
                        run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
            # 表头加粗
            if i == 0:
                for cell in table2.rows[i].cells:
                    for paragraph in cell.paragraphs:
                        for run in paragraph.runs:
                            run.font.bold = True
        # 插入第二张图片
        doc.add_heading('2.1 资源部署示意图', level=2)
        img2_para = doc.add_paragraph()
        img2_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
        img2_run = img2_para.add_run()
        img2_run.add_picture('image2.jpg', width=Inches(5))
        img2_para.add_run('\n图2:资源部署拓扑图').font.size = Pt(10)
        # 补充段落内容
        doc.add_paragraph('资源配置遵循「够用且预留扩展」原则,硬件资源可根据项目进度弹性扩容,人力资源采用「核心+外协」模式保障交付进度。')
        # 插入分页符(第二页结束)
        doc.add_page_break()
        # ========== 第三页内容 ==========
        doc.add_heading('三、项目风险评估', level=1)
        risk_para = doc.add_paragraph('通过对技术、人员、成本、进度四个维度的评估,识别出以下核心风险点及应对措施:')
        # 第三个表格:风险评估表(4行4列)
        table3 = doc.add_table(rows=4, cols=4)
        table3.style = 'Table Grid'
        table3.alignment = WD_TABLE_ALIGNMENT.CENTER
        table3_data = [
            ['风险类型', '风险等级', '影响范围', '应对措施'],
            ['技术风险', '中', '核心功能模块', '提前进行技术预研,制定备选方案'],
            ['进度风险', '低', '整体交付', '设置里程碑节点,每周进度复盘'],
            ['成本风险', '低', '预算管控', '建立成本台账,超支提前预警']
        for i, row_data in enumerate(table3_data):
            row_cells = table3.rows[i].cells
            for j, cell_text in enumerate(row_data):
                row_cells[j].text = cell_text
                for paragraph in row_cells[j].paragraphs:
                    for run in paragraph.runs:
                        run.font.size = Pt(10)
                        run.font.name = '微软雅黑'
                        run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
            if i == 0:
                for cell in table3.rows[i].cells:
                    for paragraph in cell.paragraphs:
                        for run in paragraph.runs:
                            run.font.bold = True
        # 结尾段落
        doc.add_paragraph('\n综上所述,本项目整体可控,通过科学的资源配置和风险管控措施,能够保障项目按计划交付并达到预期目标。')
        # 保存文档
        doc.save('项目报告.docx')
        print("项目报告文档已生成")
    if __name__ == '__main__':
        ensure_test_images()  # 准备测试图片
        generate_complex_doc()
    

    文档修改代码针对上述生成的文档,实现以下常见修改需求:

  • 修改标题和段落文本
  • 修改表格中的内容
  • 添加新的段落和表格
  • 修改字体样式
  • 示例代码如下:

    from docx import Document
    from docx.shared import Inches, Pt
    from docx.shared import RGBColor
    from docx.enum.table import WD_TABLE_ALIGNMENT
    from docx.enum.text import WD_ALIGN_PARAGRAPH
    from docx.oxml.ns import qn
    import os
    # 修改已生成的Word文档
    def modify_complex_doc(file_path):
        # 打开已生成的文档
        doc = Document(file_path)
        print("已打开待修改的文档")
        # ========== 1. 修改标题 ==========
        # 第一个标题是级别0的标题(主标题)
        main_title = doc.paragraphs[0]
        main_title.runs[0].text = 'XX企业数字化转型项目终版报告'  # 修改主标题文本
        main_title.runs[0].font.color.rgb = RGBColor(0, 0, 255)  # 标题改为蓝色
        main_title.runs[0].font.size = Pt(20)
        main_title.runs[0].font.name = '微软雅黑'
        main_title.runs[0]._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
        main_title.alignment = WD_ALIGN_PARAGRAPH.CENTER
        # ========== 2. 修改段落文本 ==========
        # 找到"项目概述"下的段落(可通过文本特征定位)
        for para in doc.paragraphs:
            if '本项目针对企业数字化转型需求' in para.text:
                # 清空原有内容,重新写入
                para.clear()
                new_run = para.add_run('本项目针对大型制造企业数字化转型需求,重点解决现有业务系统数据孤岛、流程不规范、决策效率低等核心问题。')
                new_run.font.size = Pt(12)
                new_run.font.name = '微软雅黑'
                new_run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
                # 追加内容
                para.add_run('\n项目升级后新增:')
                para.add_run('\n4) 供应链管理模块:打通上下游供应商数据')
                break
        # ========== 3. 修改表格内容并添加表格名 ==========
        # 表格1:项目基础信息表(第一个表格)
        table1 = doc.tables[0]
        # 修改项目编号
        table1.rows[1].cells[0].text = 'XM2026001-FINAL'
        # 修改预计工期
        table1.rows[1].cells[3].text = '10个月'
        # 给修改后的单元格文字标红
        for cell in [table1.rows[1].cells[0], table1.rows[1].cells[3]]:
            for para in cell.paragraphs:
                for run in para.runs:
                    run.font.color.rgb = RGBColor(255, 0, 0)
                    run.font.size = Pt(11)
                    run.font.name = '微软雅黑'
                    run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
        # 为表格1添加表格名(表题)
        # 找到表格1的位置,在表格上方插入表名
        table1_elem = table1._element
        table_caption1 = doc.add_paragraph('表1 项目基础信息表')
        table_caption1.alignment = WD_ALIGN_PARAGRAPH.CENTER  # 居中对齐
        table_caption1.paragraph_format.space_before = Pt(0)
        table_caption1.paragraph_format.space_after = Pt(0)
        # 设置表名字体格式
        for run in table_caption1.runs:
            run.font.size = Pt(11)
            run.font.name = '微软雅黑'
            run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
            run.font.bold = True  # 加粗
        # 将表名插入到表格上方
        table1_elem.addprevious(table_caption1._element)
        # 表格2:资源配置表(第二个表格)
        table2 = doc.tables[1]
        # 修改服务器配置
        table2.rows[3].cells[1].text = '16核32G云服务器3台(升级配置)'
        # 设置表格2单元格字体
        for row in table2.rows:
            for cell in row.cells:
                for para in cell.paragraphs:
                    for run in para.runs:
                        run.font.size = Pt(11)
                        run.font.name = '微软雅黑'
                        run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
        # 为表格2添加表格名(表题)
        table2_elem = table2._element
        table_caption2 = doc.add_paragraph('表2 项目资源配置表')
        table_caption2.alignment = WD_ALIGN_PARAGRAPH.CENTER
        for run in table_caption2.runs:
            run.font.size = Pt(11)
            run.font.name = '微软雅黑'
            run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
            run.font.bold = True
        table2_elem.addprevious(table_caption2._element)
        # ========== 4. 替换图片并规范图名 ==========
        # 先准备一张新的测试图片
        from PIL import Image
        new_img_path = 'test.png'
        if not os.path.exists(new_img_path):
            img = Image.new('RGB', (800, 600), color='lightgreen')
            img.save(new_img_path)
        # 找到第一张图片所在的段落(通过图片相关特征)
        img_para_index = -1
        for i, para in enumerate(doc.paragraphs):
            if '图1:项目整体架构图' in para.text or 'graphicData' in str(para._element.xml):
                img_para_index = i
                break
        if img_para_index != -1:
            # 清空段落中的图片和文字,重新添加
            img_para = doc.paragraphs[img_para_index]
            img_para.clear()
            # 重新添加新图片
            img_run = img_para.add_run()
            img_run.add_picture(new_img_path, width=Inches(5))
            # 添加规范的图名(图题)
            img_caption = img_para.add_run('\n图1 项目整体架构图(终版)')
            img_caption.font.size = Pt(10)
            img_caption.font.name = '微软雅黑'
            img_caption._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
            img_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
        # ========== 5. 添加新内容并为新表格加表名 ==========
        # 在第三页风险评估后添加新的段落和表格
        # 先找到风险评估标题的位置,在其后添加内容
        for i, para in enumerate(doc.paragraphs):
            if '三、项目风险评估' in para.text:
                # 添加新的子标题
                new_sub_heading = doc.add_heading('3.1 风险应对预案', level=2)
                # 插入到指定位置
                doc.paragraphs.insert(i+1, new_sub_heading)
                # 添加新段落
                new_para = doc.add_paragraph('针对高优先级风险,制定专项应对预案,包括应急响应流程、备用资源调配方案等,确保风险发生时可快速处置。')
                new_para.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
                for run in new_para.runs:
                    run.font.size = Pt(12)
                    run.font.name = '微软雅黑'
                    run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
                doc.paragraphs.insert(i+2, new_para)
                # 添加新表格(应急预案表)
                new_table = doc.add_table(rows=2, cols=2)
                new_table.style = 'Table Grid'
                new_table.alignment = WD_TABLE_ALIGNMENT.CENTER
                # 填充新表格
                new_table.rows[0].cells[0].text = '风险类型'
                new_table.rows[0].cells[1].text = '应急联系人'
                new_table.rows[1].cells[0].text = '技术风险'
                new_table.rows[1].cells[1].text = '张工 13800138000'
                # 设置新表格字体
                for row in new_table.rows:
                    for cell in row.cells:
                        for para_cell in cell.paragraphs:
                            for run in para_cell.runs:
                                run.font.size = Pt(10)
                                run.font.name = '微软雅黑'
                                run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
                # 为新表格添加表名
                new_table_caption = doc.add_paragraph('表3 风险应急联系人表')
                new_table_caption.alignment = WD_ALIGN_PARAGRAPH.CENTER
                for run in new_table_caption.runs:
                    run.font.size = Pt(11)
                    run.font.name = '微软雅黑'
                    run._element.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')
                    run.font.bold = True
                # 插入新表格名和新表格
                doc.element.body.insert(i+3, new_table_caption._element)
                doc.element.body.insert(i+4, new_table._element)
                break
        # ========== 保存修改后的文档 ==========
        doc.save('项目报告_修改版.docx')
        print("修改后的文档已保存:项目报告_修改版.docx")
    if __name__ == '__main__':
        # 确保原文档存在
        file_path = '项目报告.docx'
        if not os.path.exists(file_path):
            print("请先运行生成代码创建原始文档!")
        else:
            modify_complex_doc(file_path)
    
  • python-docx
  • python-docx docs
  •