非常游戏网
如何用Python自动化操作Word文档生成报告_利用python-docx模块

如何用Python自动化操作Word文档生成报告_利用python-docx模块

2026-05-29日常编程70685

python-docx新建文档默认页边距1英寸、字体Calibri 11pt,因不加载normal.dotm模板而用硬编码值;需显式设置section边距和Normal样式字体;add_paragraph()自带段前段后间距致空行;cell.text会清空格式,应操作paragraphs[0].runs;样式名须严格匹配。

python-docx 能生成格式规整的 Word 报告,但不能读取或修改已有文档中的复杂样式(如页眉页脚、文本框、表格嵌套样式),也不支持 .doc 格式 —— 用它写报告前,先确认你只要生成新文档,且接受 .docx 为唯一输出格式。

为什么 Document() 创建的文档默认没有页边距和字体?

新建的 Document() 实例使用的是内置的「Normal」样式,其段落、字体、页面设置均继承自 Word 默认模板(normal.dotm),但 python-docx 不加载该模板的物理文件,而是用一组极简的硬编码默认值:上下左右页边距均为 1 英寸(约 2.54 cm),正文字体为 Calibri 11pt。实际导出后打开 Word 时,会由 Word 自动补全缺失样式,但若需精确控制,必须显式设置。

  • 页边距需通过 section 对象设置:
    from docx import Document
    doc = Document()
    section = doc.sections[0]
    section.left_margin = Cm(2.5)
    section.right_margin = Cm(2.5)
  • 正文字体需修改 style
    style = doc.styles['Normal']
    font = style.font
    font.name = 'SimSun'
    font.size = Pt(12)
  • 注意:中文需同时设 font.namefont._element.rPr.rFonts.set(qn('w:eastAsia'), 'SimSun'),否则 Word 中显示为方块

add_paragraph() 插入的段落为什么总带空行?

这是 Word 的段落间距逻辑导致的:每个 Paragraph 对象默认启用「段前/段后间距」(spacing_before / spacing_after),初始值非零。即使内容为空,也会渲染出视觉空行;若连续调用多次 add_paragraph(),空行会叠加。

Python 3.14.3

微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。

  • 清除段前段后间距:
    p = doc.add_paragraph('标题')
    p.paragraph_format.space_before = Pt(0)
    p.paragraph_format.space_after = Pt(0)
  • 更稳妥的做法是复用段落对象,而非反复新建:
    title = doc.add_heading('报告摘要', level=1)
    title.paragraph_format.space_after = Pt(12)
  • 避免用 add_paragraph('') 模拟换行 —— 改用 add_run().add_break() 或直接控制 paragraph_format.line_spacing

表格里填数据时,cell.text 覆盖原有内容但不保留格式怎么办?

cell.text = 'xxx' 会清空单元格内所有 Run 并新建一个纯文本 Run,原有加粗、颜色、超链接等全部丢失。这不是 bug,而是设计使然:python-docx 的 text 属性仅用于快速赋值,不参与样式管理。

  • 保留并修改内容,应操作 cell.paragraphs[0]
    cell = table.cell(0, 0)
    p = cell.paragraphs[0]
    for run in p.runs:
    run.clear() # 清空原 run 内容
    p.add_run('新文本').bold = True
  • 插入多段内容(如带换行的地址):
    p.add_run('上海市').bold = True
    p.add_run('\n')
    p.add_run('浦东新区张江路123号')
  • 注意:表格单元格可能含多个段落(如合并单元格后手动回车),务必遍历 cell.paragraphs 而非只取 [0]

最易被忽略的是样式继承链:Word 中「标题 1」样式可能基于「标题」,而「标题」又基于「正文」—— python-docx 不解析这种层级,只认直接定义的样式名。如果你从模板文档复制样式到新文档,要确保目标样式名完全一致(包括大小写和空格),否则 doc.styles['Heading 1'] 会报 KeyError