detailed-docx:一个能保住格式的 Word 文档操作库

项目地址:

问题

用 Python 改 Word 文档里的内容,最怕的就是格式丢失。

python-docx 是 Python 生态里操作 .docx 的标准库,功能很全,但它提供的是底层能力------你得自己处理文本碎片、格式保留、合并单元格等问题。对于"改几个字但格式不能动"这种需求,裸用 python-docx 其实不太行。

detailed-docx 就是在 python-docx 之上封装的一层,专门解决格式保留问题。

Word 的内部结构:理解 Run

要理解为什么"改个字"这么难,需要先了解 Word 文档的内部结构。

一个段落(Paragraph)并不是一整段文字,而是由多个 Run 拼接而成。每个 Run 是一段格式一致的文本片段:

复制代码
段落: "北京公司在2023年取得了非常优秀的业绩"

  Run[0]: "北京公司"     → 粗体, 蓝色, 14pt
  Run[1]: "在2023年取得了" → 常规, 黑色, 12pt
  Run[2]: "非常优秀"     → 粗体, 斜体, 红色
  Run[3]: "的业绩"       → 常规, 黑色, 12pt

每个 Run 在 XML 层面有独立的格式节点 <w:rPr>,这就是 Word 实现"一段话里混合多种格式"的机制。

问题在于:Run 的拆分是不可控的 。Word 会因为拼写检查、编辑历史、中英文切换等原因,自动把文字拆成碎片。你以为 "北京公司" 在一个 Run 里,实际上可能被拆成 "北京""公司" 两个 Run。这导致直接搜索 paragraph.text 能找到,但逐个 Run 遍历却找不到完整匹配。

如果你直接写 paragraph.text = "新内容",python-docx 会把所有 Run 清空再重建------格式全没了

核心算法:跨 Run 映射与替换

detailed-docx 的核心是一个字符位置映射算法:

复制代码
1. 拼接所有 Run 的文本 → full_text = "北京公司在2023年取得了非常优秀的业绩"
2. 构建映射表:每个字符位置属于哪个 Run
3. 在 full_text 上搜索目标文本
4. 将匹配区间映射回各个 Run,逐个修改其 text 属性
5. 关键:只改 text,不动 <w:rPr> 格式节点

替换 "北京公司""上海分公司" 的实际操作:

  • Run[0] 的 text 从 "北京公司" 改成 "上海分公司"<w:rPr>(粗体+蓝色+14pt)完全不动
  • 如果匹配横跨多个 Run,后续 Run 只清空被命中的文字部分

这样就可以做到文本变了但是格式原封不动。

格式修改:增量叠加

修改格式同样是,保证只动你指定的,不碰其他的:

python 复制代码
# "非常优秀" 原来是 {粗体, 斜体, 红色}
editor.modify_format("非常优秀", {"underline": True})
# 结果:{粗体, 斜体, 红色, 下划线} ← 只新增,不覆盖

API 概览

python 复制代码
from my_docx import DocxEditor

# ── 读取 ──
editor = DocxEditor("input.docx")
editor.get_structural_map()        # 段落 + 表格 + 节的完整结构
editor.get_run_details(para_idx=1) # 查看某段的 Run 碎片和精确格式

# ── 替换(自动跨 Run,自动保格式)──
editor.replace_text("旧词", "新词")
editor.replace_in_table(0, 1, 3, "旧值", "新值")

# ── 格式(增量叠加)──
editor.modify_format("重点内容", {"bold": True, "color": "FF0000"})

# ── 写入空单元格 ──
editor.set_table_cell_text(0, 0, 3, "张三", {"name": "黑体", "size": 12})

# ── 创建 ──
editor = DocxEditor.create_new()
editor.add_heading("标题", level=1)
editor.add_paragraph("正文", fmt={"name": "宋体", "size": 12})

# ── 删除 ──
editor.delete_paragraph(3)
editor.delete_table_row(0, 2)

editor.save("output.docx")
相关推荐
IT方大同2 小时前
RT_thread(RTOS实时操作系统)线程的创建与切换
c语言·开发语言·嵌入式硬件
智算菩萨2 小时前
【OpenGL】6 真实感光照渲染实战:Phong模型、材质系统与PBR基础
开发语言·python·游戏引擎·游戏程序·pygame·材质·opengl
jinanwuhuaguo2 小时前
OpenClaw深度沟通渠道-全景深度解构
大数据·开发语言·人工智能·openclaw
是翔仔呐2 小时前
第14章 CAN总线通信全解:底层原理、帧结构与双机CAN通信实战
c语言·开发语言·stm32·单片机·嵌入式硬件·学习·gitee
2401_878530212 小时前
机器学习与人工智能
jvm·数据库·python
客卿1232 小时前
用两个栈实现队列
android·java·开发语言
leaves falling2 小时前
C++模板初阶:让代码“复制粘贴”自动化
开发语言·c++·自动化
代码探秘者2 小时前
【算法】吃透18种Java 算法快速读写模板
数据结构·数据库·python·算法·spring
java1234_小锋2 小时前
Java高频面试题:谈谈你对SpringBoot的理解?
java·开发语言·spring boot