Word 文档处理 (DOCX) - 完整指南
提示: 这是完整的技术指南。如果你是第一次了解这个技能,建议先阅读概览页面。
📋 概述
.docx 文件本质上是一个 ZIP 压缩包,包含 XML 文件和其他资源(图片、样式等)。你可以解压、读取或编辑这些文件。
根据不同任务,有以下工具和工作流可用:
| 任务类型 | 推荐工具 | 使用场景 |
|---|---|---|
| 读取/分析 | Pandoc | 提取文本、查看内容 |
| 创建新文档 | docx-js | 从头生成 Word 文档 |
| 编辑(简单) | OOXML 编辑 | 自己的文档,简单修改 |
| 编辑(专业) | Redlining 工作流 | 他人文档、需追踪更改 |
🔍 工作流决策树
读取/分析内容
使用下面的"文本提取"或"原始 XML 访问"部分。
创建新文档
使用"创建新 Word 文档"工作流。
编辑现有文档
你自己的文档 + 简单更改
使用"基础 OOXML 编辑"工作流他人的文档
使用 "Redlining 工作流"(推荐默认)法律、学术、商业或政府文档
使用 "Redlining 工作流"(必须)
📖 读取和分析内容
方法 1: 文本提取
如果只需读取文档的文本内容,应该使用 pandoc 将文档转换为 Markdown。Pandoc 提供出色的文档结构保留支持,并可显示追踪更改:
# 转换文档为 Markdown(显示追踪更改)
pandoc --track-changes=all path-to-file.docx -o output.md
# 选项:
# --track-changes=accept 接受所有更改
# --track-changes=reject 拒绝所有更改
# --track-changes=all 显示所有更改(默认)
使用场景:
- 快速查看文档内容
- 提取纯文本
- 分析文档结构
- 查看追踪更改历史
方法 2: 原始 XML 访问
以下情况需要原始 XML 访问:
- 评论 (comments)
- 复杂格式
- 文档结构
- 嵌入媒体
- 元数据
对于这些功能,需要解压文档并读取原始 XML 内容。
解压文件
python ooxml/scripts/unpack.py <office_file> <output_directory>
关键文件结构
解压后的目录结构:
unpacked/
├── word/
│ ├── document.xml # 主文档内容
│ ├── comments.xml # 评论(在 document.xml 中引用)
│ ├── styles.xml # 样式定义
│ ├── media/ # 嵌入的图片和媒体文件
│ └── ...
├── docProps/ # 文档属性和元数据
└── _rels/ # 关系文件
追踪更改标记:
<w:ins>- 插入内容<w:del>- 删除内容
📝 创建新 Word 文档
当从头创建新 Word 文档时,使用 docx-js,这是一个允许使用 JavaScript/TypeScript 创建 Word 文档的库。
工作流
必读 - 阅读完整文件: 阅读
docx-js.md(约 500 行)从头到尾完整阅读。不要设置任何范围限制。阅读完整文件内容以了解详细语法、关键格式规则和最佳实践,然后再进行文档创建。创建 JavaScript/TypeScript 文件,使用 Document、Paragraph、TextRun 组件(可以假设所有依赖项已安装,如果没有,请参阅下面的依赖项部分)
导出为 .docx,使用
Packer.toBuffer()
基本示例
const docx = require('docx');
const fs = require('fs');
const { Document, Paragraph, TextRun, Packer } = docx;
// 创建文档
const doc = new Document({
sections: [{
properties: {},
children: [
// 标题
new Paragraph({
text: "文档标题",
heading: "Heading1"
}),
// 普通段落
new Paragraph({
children: [
new TextRun({
text: "这是一段 ",
bold: false
}),
new TextRun({
text: "加粗文本",
bold: true
}),
new TextRun({
text: ",还有 ",
}),
new TextRun({
text: "斜体文本",
italics: true
})
]
}),
// 带格式的段落
new Paragraph({
text: "这是居中对齐的段落",
alignment: "center"
})
]
}]
});
// 导出为 .docx 文件
Packer.toBuffer(doc).then(buffer => {
fs.writeFileSync("my-document.docx", buffer);
console.log("文档创建成功!");
});
高级功能
详细的 API 文档和示例请查看 docx-js 完整文档,包括:
- 表格创建
- 图片插入
- 页眉页脚
- 列表(有序/无序)
- 样式和格式
- 页面设置
✏️ 编辑现有 Word 文档
编辑现有 Word 文档时,使用 Document 库(一个用于 OOXML 操作的 Python 库)。该库自动处理基础设施设置,并提供文档操作方法。对于复杂场景,可以通过库直接访问底层 DOM。
工作流
必读 - 阅读完整文件: 阅读
ooxml.md(约 600 行)从头到尾完整阅读。不要设置任何范围限制。阅读完整文件内容以了解 Document 库 API 和直接编辑文档文件的 XML 模式。解压文档:
python ooxml/scripts/unpack.py <office_file> <output_directory>创建并运行 Python 脚本,使用 Document 库(见 ooxml.md 中的"Document Library"部分)
打包最终文档:
python ooxml/scripts/pack.py <input_directory> <office_file>
Document 库提供高级方法用于常见操作,并提供直接 DOM 访问用于复杂场景。
基本编辑示例
from ooxml import Document
# 加载解压的文档
doc = Document('unpacked')
# 查找并替换文本
nodes = doc.get_node('w:t', text='旧文本')
for node in nodes:
node.text = '新文本'
# 保存更改
doc.save()
完整的 API 和高级用法请查看 OOXML 完整文档。
🔴 Redlining 工作流(文档审阅)
这个工作流允许你在 OOXML 中实现之前,使用 markdown 规划全面的追踪更改。
关键
对于完整的追踪更改,你必须系统性地实现所有更改。
核心原则
批处理策略: 将相关更改分组为 3-10 个更改的批次。这使调试易于管理同时保持效率。在进入下一批之前测试每一批。
原则:最小、精确的编辑
实现追踪更改时,仅标记实际更改的文本。重复未更改的文本会使编辑更难审阅,并显得不专业。
将替换分解为:[未更改的文本] + [删除] + [插入] + [未更改的文本]
通过从原始提取 <w:r> 元素并重用它,为未更改的文本保留原始运行的 RSID。
示例 - 将"30 天"改为"60 天"
# ❌ 错误 - 替换整个句子
'<w:del><w:r><w:delText>合同期限为 30 天。</w:delText></w:r></w:del>' \
'<w:ins><w:r><w:t>合同期限为 60 天。</w:t></w:r></w:ins>'
# ✅ 正确 - 仅标记更改内容,保留原始 <w:r> 的未更改文本
'<w:r w:rsidR="00AB12CD"><w:t>合同期限为 </w:t></w:r>' \
'<w:del><w:r><w:delText>30</w:delText></w:r></w:del>' \
'<w:ins><w:r><w:t>60</w:t></w:r></w:ins>' \
'<w:r w:rsidR="00AB12CD"><w:t> 天。</w:t></w:r>'
追踪更改工作流(详细步骤)
步骤 1: 获取 Markdown 表示
将文档转换为 Markdown,保留追踪更改:
pandoc --track-changes=all path-to-file.docx -o current.md
这让你能够:
- 查看文档的当前状态
- 识别需要更改的部分
- 理解文档结构
步骤 2: 识别并分组更改
审阅文档并识别所有需要的更改,将它们组织成逻辑批次:
位置方法(用于在 XML 中查找更改):
- 章节/标题编号(例如,"第 3.2 节"、"第 IV 条")
- 段落标识符(如果有编号)
- 带有唯一周围文本的 Grep 模式
- 文档结构(例如,"第一段"、"签名块")
- 不要使用 markdown 行号 - 它们不映射到 XML 结构
批次组织(每批 3-10 个相关更改):
- 按章节: "批次 1: 第 2 节修订"、"批次 2: 第 5 节更新"
- 按类型: "批次 1: 日期更正"、"批次 2: 当事人名称更改"
- 按复杂度: 从简单的文本替换开始,然后处理复杂的结构更改
- 按顺序: "批次 1: 第 1-3 页"、"批次 2: 第 4-6 页"
示例批次规划:
## 批次 1: 日期更新(4 个更改)
1. 第 1 节: "2024年1月1日" → "2024年3月1日"
2. 第 3 节: "2024年6月30日" → "2024年9月30日"
3. 附件 A: "2024年2月" → "2024年4月"
4. 签名页: "2024-01-15" → "2024-03-15"
## 批次 2: 当事人信息更新(3 个更改)
1. 序言: "ABC公司" → "ABC技术有限公司"
2. 第 2.1 节: 添加新的联系人信息
3. 签名块: 更新签署人职位
## 批次 3: 条款修订(5 个更改)
1. 第 4.3 节: "30天" → "60天"
2. 第 5.1 节: 删除过时条款
3. 第 5.2 节: 添加新的违约条款
4. 第 6 节: 修改赔偿限额
5. 第 7 节: 更新争议解决条款
步骤 3: 阅读文档并解压
必读 - 阅读完整文件: 阅读
ooxml.md(约 600 行)从头到尾完整阅读。不要设置任何范围限制。特别注意"Document Library"和"Tracked Change Patterns"部分。解压文档:
python ooxml/scripts/unpack.py <file.docx> <dir>记录建议的 RSID: 解压脚本会建议一个用于追踪更改的 RSID。复制此 RSID 以在步骤 4b 中使用。
示例输出:
建议的 RSID: 00AB12CD
步骤 4: 批量实现更改
将更改逻辑分组(按章节、类型或接近度)并在单个脚本中一起实现它们。这种方法:
- 使调试更容易(较小的批次 = 更容易隔离错误)
- 允许增量进展
- 保持效率(3-10 个更改的批次大小效果很好)
建议的批次分组:
- 按文档章节(例如,"第 3 节更改"、"定义"、"终止条款")
- 按更改类型(例如,"日期更改"、"当事人名称更新"、"法律术语替换")
- 按接近度(例如,"第 1-3 页的更改"、"文档前半部分的更改")
对于每批相关更改:
a. 将文本映射到 XML: Grep word/document.xml 中的文本以验证文本如何跨 <w:r> 元素分割。
grep -n "要查找的文本" unpacked/word/document.xml
b. 创建并运行脚本: 使用 get_node 查找节点,实现更改,然后 doc.save()。
参见 ooxml.md 中的 "Document Library" 部分获取模式。
示例脚本(批次 1: 日期更新):
from ooxml import Document
# 加载文档
doc = Document('unpacked')
# 更改 1: 第 1 节日期
nodes = doc.get_node('w:t', text='2024年1月1日')
for node in nodes:
# 创建追踪更改
parent = node.getparent()
# ... 实现追踪更改逻辑(见 ooxml.md)
# 更改 2-4: 类似处理...
# 保存更改
doc.save()
重要提示
在编写脚本之前,始终 grep word/document.xml 以获取当前行号并验证文本内容。每次脚本运行后行号会更改。
步骤 5: 打包文档
所有批次完成后,将解压的目录转换回 .docx:
python ooxml/scripts/pack.py unpacked reviewed-document.docx
步骤 6: 最终验证
对完整文档进行全面检查:
转换最终文档为 Markdown:
pandoc --track-changes=all reviewed-document.docx -o verification.md验证所有更改都已正确应用:
# 原始短语应该找不到 grep "旧文本" verification.md # 替换短语应该找到 grep "新文本" verification.md检查没有引入意外更改
- 对比原始和修订的 markdown
- 确认所有追踪更改都按预期显示
🖼️ 将文档转换为图片
要可视化分析 Word 文档,使用两步过程将其转换为图片:
步骤 1: 转换 DOCX 为 PDF
soffice --headless --convert-to pdf document.docx
步骤 2: 转换 PDF 页面为 JPEG 图片
pdftoppm -jpeg -r 150 document.pdf page
这会创建类似 page-1.jpg、page-2.jpg 等文件。
选项
-r 150: 设置分辨率为 150 DPI(调整以平衡质量/大小)-jpeg: 输出 JPEG 格式(如果喜欢 PNG 使用-png)-f N: 要转换的第一页(例如,-f 2从第 2 页开始)-l N: 要转换的最后一页(例如,-l 5在第 5 页停止)page: 输出文件的前缀
特定范围示例
# 仅转换第 2-5 页
pdftoppm -jpeg -r 150 -f 2 -l 5 document.pdf page
💻 代码风格指南
重要
生成 DOCX 操作代码时:
- 编写简洁的代码
- 避免冗长的变量名和冗余操作
- 避免不必要的 print 语句
📚 参考文档
此技能包含详细的参考文档:
docx-js 完整文档 (~500 行) - JavaScript/TypeScript 创建 Word 文档
- Document、Paragraph、TextRun API
- 表格、图片、页眉页脚
- 样式和格式详解
OOXML 完整文档 (~600 行) - Python 编辑 Word 文档
- Document 库 API
- 追踪更改模式
- XML 结构详解
- 高级编辑技巧
使用建议
- 创建新文档前: 先阅读 docx-js 文档
- 编辑现有文档前: 先阅读 OOXML 文档
🔧 依赖项
所需依赖项(如果不可用则安装):
系统依赖
# Pandoc(用于文本提取)
sudo apt-get install pandoc
# LibreOffice(用于 PDF 转换)
sudo apt-get install libreoffice
# Poppler(用于 pdftoppm 将 PDF 转换为图片)
sudo apt-get install poppler-utils
JavaScript/Node.js 依赖
# docx(用于创建新文档)
npm install docx
Python 依赖
# defusedxml(用于安全的 XML 解析)
pip install defusedxml
💡 最佳实践
✅ 推荐做法
选择正确的工作流
- 专业文档(法律/学术/商业)→ Redlining 工作流
- 简单编辑自己的文档 → OOXML 基础编辑
- 创建新文档 → docx-js
批量处理追踪更改
- 每批 3-10 个相关更改
- 按章节或类型分组
- 测试每批后再继续
最小化追踪更改标记
- 仅标记实际更改的文本
- 保留未更改文本的原始
<w:r>元素 - 使用建议的 RSID
验证更改
- 使用 pandoc 转换为 markdown 检查
- Grep 验证所有更改已应用
- 在 Word 中打开查看追踪更改显示
代码简洁性
- 避免冗长的变量名
- 移除不必要的 print 语句
- 关注核心逻辑
❌ 避免事项
不要跳过完整文档阅读
- docx-js.md 和 ooxml.md 包含关键细节
- 不设置范围限制,完整阅读
不要在专业文档中直接替换
- 法律/学术/政府文档必须使用追踪更改
- 直接替换会丢失审计跟踪
不要标记过多未更改文本
- 仅标记实际更改的词/短语
- 保留周围的原始文本
不要忘记批处理
- 一次实现所有更改会使调试困难
- 分批处理,逐步验证
⚠️ 常见问题
Q: 如何判断应该使用哪种工作流?
A: 参考决策树:
- 读取 → Pandoc
- 创建 → docx-js
- 编辑(自己的,简单) → OOXML
- 编辑(他人的,专业) → Redlining
Q: 为什么我的追踪更改在 Word 中不显示?
A: 检查:
- 是否使用了正确的 XML 标签(
<w:ins>、<w:del>) - RSID 是否正确
- XML 结构是否完整
- 文档是否正确打包
Q: 如何找到要修改的文本在 XML 中的位置?
A:
# 在 document.xml 中 grep 查找
grep -n "要查找的文本" unpacked/word/document.xml
# 查看周围上下文
grep -C 3 "要查找的文本" unpacked/word/document.xml
Q: 批处理策略的最佳批次大小是多少?
A:
- 理想: 3-10 个更改/批次
- 太小(1-2): 效率低
- 太大(20+): 调试困难
按复杂度调整:
- 简单文本替换:5-10 个/批次
- 复杂结构更改:3-5 个/批次
📖 相关页面
文档更新: 2025-11-20
原始来源: document-skills/docx/SKILL.md