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> 格式节点

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

  • Run0 的 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")
相关推荐
IDIOSF1 分钟前
R语言 下载安装教程(附安装包)R语言4.5安装步骤(保姆级)
开发语言·其他·r语言
乱七八糟的屋子3 分钟前
LibYAML超全教程-C语言YAML解析与生成
c语言·开发语言·配置文件·yaml解析·libyaml·开源库实战
X1A0RAN3 分钟前
Python 并发请求性能优化实战
python·性能优化·并发编程
java_logo5 分钟前
Docker 部署 WPS 在线办公套件,浏览器即可编辑 Word、Excel、PPT
docker·word·wps·wps部署教程·wps免费版·轩辕镜像·docker部署教程
陈同学xxx9 分钟前
Hermes Agent 接入飞书,在手机上随时聊天
linux·python·飞书
paopaokaka_luck10 分钟前
基于Springboot3+Vue3的宠物殡葬管理系统(webSocket实时通讯、接入腾讯地图、支付宝沙盒支付、Echarts图形化分析)
java·开发语言·网络·后端
卷无止境13 分钟前
Python 中基于 Qt 的 GUI 库授权方式全解析
后端·python
逝水无殇14 分钟前
HTML 元素详解
开发语言·前端·html
Lhappy嘻嘻26 分钟前
网络初识|基础入门:局域网广域网、IP 端口、TCP/IP 五层模型与封装解封装全过程
java·开发语言·网络·笔记·网络协议·tcp/ip
卷无止境27 分钟前
Guardrails.ai:为大语言模型加一道"安全阀"
后端·python