DOCX 创建、编辑和分析
.docx 文件是 XML 文件的 ZIP 存档。根据任务选择方法:
| 任务 | 方法 |
|---|---|
| 创建新文档 | 编写一个 docx (npm) 脚本 — 见下文注意事项 |
| 编辑现有文档 | unzip → 编辑 word/document.xml → zip (docx-js 无法打开现有文件) |
| 读取内容 | pandoc -t markdown file.docx |
下文中的脚本路径均相对于该技能目录。
使用 docx-js 创建 — 注意事项
docx 已预安装 — 不要先运行 npm install;直接编写脚本并使用 require('docx')。仅当该 require 失败时:npm install docx。模型知道 API;以下是容易出错的地方:
- 页面尺寸默认为 A4。 如需美式信纸,请设置
page: { size: { width: 12240, height: 15840 } }(DXA;1440 = 1 英寸)。 - **横向:**传入纵向尺寸并指定
orientation: PageOrientation.LANDSCAPE— docx-js 会在内部交换宽度/高度。 - **表格需要双重宽度:**在表格上设置
columnWidths,并在每个单元格上设置width,两者均使用WidthType.DXA(在 Google Docs 中,PERCENTAGE会失效)。列宽之和必须等于表格宽度。 - **表格底纹:**使用
ShadingType.CLEAR,切勿使用SOLID(会渲染为纯黑色)。 - **列表:**切勿直接插入
•字符;应使用带LevelFormat.BULLET的numbering配置。 ImageRun需要指定type: ("png","jpg", …)。PageBreak必须位于Paragraph内部。- 切勿使用
\n— 请使用单独的Paragraph元素。 - **目录:**标题必须使用内置的
HeadingLevel.*;自定义标题样式需要设置outlineLevel,否则不会出现在目录中。 - 不要使用表格作为水平线 — 改用段落的底部边框。
- **点前导/同一行右对齐:**在
TextRun内使用PositionalTab(alignment: PositionalTabAlignment.RIGHT,leader: PositionalTabLeader.DOT),不要直接使用.或空格填充。
验证输出
编写 .docx 后,将其渲染并查看:
python scripts/office/soffice.py --headless --convert-to pdf output.docx
pdftoppm -jpeg -r 100 output.pdf page
ls page-*.jpg # 然后读取这些图像
pdftoppm 会用总页数的位数对页码进行零填充 (page-01.jpg…page-12.jpg)。
编辑现有文档
旧版 .doc 文件必须首先转换:python scripts/office/soffice.py --headless --convert-to docx file.doc。
unzip -q doc.docx -d unpacked/
find unpacked -type l -delete # 删除符号链接条目 — 来自外部的docx文件不可信
python scripts/merge_runs.py unpacked/ # 合并碎片化的文本片段,使文本可查找
# 原地编辑 unpacked/word/document.xml — 不要重新格式化或美化
(cd unpacked && rm -f ../out.docx && zip -Xr ../out.docx .)
python scripts/office/validate.py out.docx --original doc.docx # XSD 检查;--auto-repair 修复常见问题
# 需要修订?添加 --author "<修订者姓名>" 以检查每次编辑是否都被跟踪
Word 会将文本分散到多个 <w:r> 片段(修订 ID、拼写检查标记),因此您在文档中看到的短语通常不作为连续字符串存在于 XML 中。merge_runs.py 合并 word/document.xml 中相邻且格式相同的片段,不更改内容或渲染效果;它也接受 .docx 文件作为直接参数 (python scripts/merge_runs.py doc.docx -o merged.docx)。
跟踪修订: 进行修订时,使用 --author "<修订者姓名>" 进行验证(需要 --original)— 它会报告您修改但缺少 <w:ins>/<w:del> 包装的任何文本,这在接受视图中很容易发生且不可见。使用 w:id、w:author、w:date 属性将文本段包装在 <w:ins>/<w:del> 中。在 <w:del> 内部,文本元素是 <w:delText>,而不是 <w:t>。删除的段落标记 (<w:pPr><w:rPr><w:del w:id=".." w:author=".." w:date=".."/></w:rPr></w:pPr>) 表示“将此段落合并到下一段” — 因此彻底删除一个段落就是该标记加上每个文本段的 <w:del>。<w:del/> 必须位于 rPr 的其他子元素之前;它们的顺序由模式强制规定。
要生成接受所有跟踪修订后的干净副本:python scripts/accept_changes.py in.docx out.docx。
接受删除的段落标记应将该段落与其下方的段落连接,因此所有文本段都被删除的段落应该消失。Word 会这样做;accept_changes.py 和 pandoc --track-changes=accept 并非总是如此。两者以同样的方式失败 — 它们会剥离删除的文本,但留下空段落,当其是自动编号时,会显示为一个多余的空项目符号:
pandoc --track-changes=accept从不连接段落。accept_changes.py(LibreOffice) 正确连接它们,除非被删除的段落后面跟着一个空的间隔段落。
在任一视图中出现空项目符号都是该视图的伪影,而不是文档的缺陷。请在 XML 中检查段落删除。
评论
评论需要六个交叉关联的文件。使用辅助脚本 — 当您还要编辑 document.xml 时使用目录模式(节省了解压/重新压缩周期),否则使用 .docx 直接模式:
# 针对已解压的目录(当同时放置标记时首选)
python scripts/comment.py unpacked/ "费用与开支上限过低"
python scripts/comment.py unpacked/ "同意" --parent 0
# 直接针对 .docx 文件
python scripts/comment.py contract.docx "这个上限太低了" -o annotated.docx
该脚本会写入 comments.xml、commentsExtended.xml、commentsIds.xml、commentsExtensible.xml、关系文件以及内容类型覆盖。评论 ID 自动分配。然后它会输出 <w:commentRangeStart>/<w:commentRangeEnd>/<w:commentReference> 片段,以便添加到 word/document.xml 中,使评论锚定到特定文本 — 在您放置这些标记之前,评论存在但不可见。
依赖项
docx (npm,预安装 — 仅在 require('docx') 失败时安装) · pandoc · LibreOffice (soffice) · pdftoppm (Poppler)
该技能由 Anthropic 创建和维护。此处按原样使用,仅修改了前置元数据;详情请参阅 LICENSE.txt。