Word 图片 / 表格题注与题注目录
用途
批量为 .docx 文档中的图片、表格插入规范化题注,并生成可自动更新的题注目录。
题注结构:
<上级标题文字><sep><标签><gap><SEQ 域编号> [说明文字]
默认效果(图片用「图」、表格用「表」,各自独立编号):
专项数据接入管理 图 - 1 专项数据接入流程
数据注册 图 - 2 数据注册图示
销售明细 表 - 1
样式默认:宋体、五号(10.5pt)、居中;位于图片 / 表格的下方一行。
何时使用
- 用户要求给 Word 里的图片、表格加题注("图 - 1""表 - 1""图表 - 1")
- 题注需要带上所属章节标题文字
- 需要生成「图目录」「表目录」「图表目录」,且带页码
- 需要把已有题注批量改写成统一格式、重新编号
工作流程
1. 定位目标文档
确认要处理的 .docx 路径。用户未明确给出时,先在桌面、文档库等常见目录查找,或让用户提供。不要猜测。
2. 准备 Python 环境
脚本依赖 python-docx。按以下顺序探测一个可用的解释器:
# Windows 本机常用位置,逐个测试 python-docx 是否可用
for p in "D:/Programs/Python/Python38/python.exe" \
"C:/Users/<用户>/.workbuddy/binaries/python/envs/default/Scripts/python.exe" \
"$(which python 2>/dev/null)"; do
"$p" -c "import docx; print('OK:', '$p')" 2>/dev/null && break
done
托管环境若无外网无法安装 python-docx,优先使用用户本机的系统 Python。安装命令:
python -m pip install python-docx -i https://pypi.tuna.tsinghua.edu.cn/simple
确认可用后,把该解释器路径记为 $PY,后续命令统一使用。
3. 先预览,再执行
务必先跑 --dry-run,把将要插入/改写的题注列表给用户确认,尤其是标题层级是否符合预期:
"$PY" scripts/add_captions.py "文档.docx" --dry-run
确认后生成结果(默认输出 文档_已加题注.docx,原文件不动):
"$PY" scripts/add_captions.py "文档.docx" --update-fields
--update-fields 会调用本机 Word/WPS 更新域,让目录直接带上页码(不更新域则只有域占位)。
4. 校验结果
"$PY" -c "
import re
from docx import Document
from docx.oxml.ns import qn
d = Document('文档_已加题注.docx')
for i, ch in enumerate(d.element.body.iterchildren()):
if ch.tag != qn('w:p'):
continue
t = ''.join(a.text or '' for a in ch.findall('.//' + qn('w:t')))
if re.search(r'(图|表|图表)\s*-\s*\d', t):
x = ch.xml
print(repr(t), re.findall(r'<w:jc[^/]*/>', x),
re.findall(r'<w:sz w:val=\"\d+\"/>', x)[:1],
re.findall(r'eastAsia=\"[^\"]+\"', x)[:1])
"
检查项:题注条数是否等于图片数 + 表格数;是否居中;字号 sz=21;字体 eastAsia="宋体"。
5. 交付
用 present_files 展示结果文档与脚本。提醒用户:增删图片后在 Word 中「更新域」即可自动重排编号与页码。
核心参数
| 参数 | 默认 | 说明 |
|---|---|---|
--image-label |
图 |
图片标签,可选 图 / 表 / 图表 |
--table-label |
表 |
表格标签 |
--label |
— | 图片与表格统一标签(此时共用一套编号) |
--heading-depth N |
2 |
取往上第 N 级标题作前缀:2 章级、1 最近一级、0 不加标题 |
--heading-mode |
single |
single=只取往上第 N 级;concat=拼接往上 N 级 |
--keep-numbering |
关 | 保留标题中的自动编号(默认去掉「第一章 」「1.1 」) |
--title-sep |
空格 | 多级标题之间的连接符 |
--seq-id |
同标签 | SEQ 域标识符 |
--sep / --gap |
/ - |
标题与标签、标签与编号之间的分隔符 |
--font / --size / --align / --bold |
宋体 / 10.5 / center / 关 | 题注字体字号对齐 |
--toc-mode |
field |
field=Word 域目录(可带页码)、static=纯文字、none=不生成 |
--toc-position |
start |
start / end |
--update-fields |
关 | 调用 Word 更新域,目录立即带页码(推荐) |
--keep-existing |
关 | 保留已有题注不改写 |
--drop-desc |
关 | 丢弃原题注中的说明文字 |
--overwrite |
关 | 重建已存在的目录 |
--per-heading |
关 | 每个一级标题内重新编号(此时编号改用纯文本) |
--no-seq |
关 | 编号不用 SEQ 域,写死数字 |
-o 文件 / --inplace |
— | 指定输出 / 覆盖原文件 |
--dry-run |
关 | 只预览不写文件 |
不带任何参数运行会弹出文件选择对话框。典型组合:
# 默认:图 - N / 表 - N,各取往上第 2 级标题
add_captions.py 文档.docx --update-fields
# 图和表统一叫「图表」,共用一套编号
add_captions.py 文档.docx --label 图表 --update-fields
# 只要最近一级标题
add_captions.py 文档.docx --heading-depth 1 --update-fields
# 拼接两级标题、用斜杠连接
add_captions.py 文档.docx --heading-mode concat --title-sep " / " --update-fields
# 批量处理整个目录
add_captions.py ./目录 --update-fields
完整用法与常见问题排查见 references/usage.md。
关键实现要点(踩过的坑)
修改 scripts/add_captions.py 时必须保持以下行为:
- 编号必须是 SEQ 域,不能写死数字。题注段落由「文字 run + SEQ 域 run + 结果缓存」组成,这样在 Word 里「更新域」能自动重排。
- SEQ 域有两种 XML 形态,识别已有题注时必须同时兼容:
-fldChar形式:指令在<w:instrText>内
-<w:fldSimple w:instr="SEQ 图 ...">:指令在w:instr属性里 —— Word 更新域后会改写成这种,只认第一种会导致重复插入题注。
同理,TOC 域的两种形态也要都识别。
3. 已有题注要改写,不能新增。很多文档本来就有 Word 原生题注(如「图 14专项数据接入流程」),必须识别后重建该段落并重新编号,同时保留原有说明文字(除非 --drop-desc)。
4. 中文字体必须写在 rFonts 的 w:eastAsia 属性上,只写 w:ascii 对中文无效。五号 = 10.5pt = sz=21(半磅)。
5. 图片识别用 w:drawing / w:pict;表格识别顶层 w:tbl。截图形式的"表格"无法识别,需先转成可编辑表格——遇到题注数量明显少于预期时,主动向用户提示这一点。
6. 标题层级判定:优先读段落样式(标题 N / Heading N),兼容自定义样式的大纲级别 w:outlineLvl。去编号时只删「第一章 」「1.1 」「一、」「(一)」这类前缀,数字后必须跟分隔符或空格,避免误删「2023年总结」。
7. 幂等性:重复运行不得产生重复题注或目录;新增/改写前都要先检测已有题注。
8. 目录用 Word 原生 TOC \c "标签" 域,不用写死文字。图片、表格标签不同时分别生成「图目录」「表目录」;文档中没有表格时不生成空的「表目录」。
文件清单
scripts/add_captions.py— 主程序(命令行工具),用法摘要见文件头部文档字符串references/usage.md— 完整使用说明:全部参数、9 个典型场景、常见问题排查表;需要向用户产出说明文档时以它为蓝本