关于 kimi-docx
kimi-docx 是指导创建与编辑 DOCX 文档的技能,面向需要生成或修改 Word 文件的用户。它区分新建与编辑流程,并强调保留原文档格式及验证输出。
主要功能
- 01创建 DOCX 并执行结构验证
- 02通过 XML 保留编辑时的格式
- 03支持批注与修订标记处理
- 04提供文档内容与结构校验
适用场景
- 01根据需求创建 Word 报告
- 02在原有 DOCX 中修改内容并保留样式
- 03检查文档中的批注和修订
- 04验证 DOCX 的文本内容与结构
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ thvroyal/ kimi-skills --skill kimi-docx安装后在 Claude Code 中输入/kimi-docx确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/templates/CJKExample.csExample.csKimiDocx.csprojProgram.csreferences/EditingGuide.mdscripts/__init__.pydocxfix_element_order.pygenerate_backgrounds.pygenerate_chart.pygenerate_inkwash_backgrounds.pyvalidate_all.pyvalidate_docx.pyscripts/docx_lib/__init__.pybusiness_rules.pyconstants.pyelement_order.pyscripts/docx_lib/editing/__init__.pycomments.pycontext.pyhelpers.pyrevisions.pyxml_tolerance.pyscripts/docx_lib/editing/tests/test_xml_tolerance.pyvalidator/ValidatorValidator.deps.jsonValidator.pdbValidator.runtimeconfig.json详细介绍
第 1 部分:目标
⚠️ 何时解压与何时读取
为保留源文档中的任何格式,必须解压并解析 XML。
读取工具仅返回纯文本——字体、颜色、对齐方式、边框和样式都会丢失。
| 需求 | 方法 |
|---|---|
| 仅需文本内容(总结、分析、翻译) | 使用读取工具即可 |
| 需要格式信息(复制样式、保留布局、填充模板) | 解压并解析 XML |
| 需要结构与批注/修订记录 | pandoc input.docx -t markdown |
核心原则
-
保留格式——编辑现有文档时,保留原有格式。克隆并修改,切勿重新创建。
-
正确实现功能——批注需要多文件同步。修订记录需要修订标记。使用正确的结构。
切勿使用 python-docx/docx-js 作为备用方案。 这些库生成的输出质量低于直接操作 XML。
源文档原则
提供了模板 = 作为表单填写者,而非设计师。
- 格式由用户决定
- 任务:替换占位符,而非重新设计
- 就像填写 PDF 表单——不要重新设计
没有模板 = 作为设计师。 根据场景自由设计。
对于 .doc(旧版格式),先使用 libreoffice --headless --convert-to docx 转换。
第 2 部分:执行
文件结构
docx/
├── SKILL.md ← This file (entry point + reference)
├── references/
│ └── EditingGuide.md → Complete Python editing tutorial (comments, track changes, 5-file sync)
├── scripts/
│ ├── docx → Unified entry (the only script to call)
│ ├── fix_element_order.py → Auto-fix XML element ordering
│ ├── validate_docx.py → Business rule validation
│ ├── generate_backgrounds.py → Morandi style backgrounds
│ ├── generate_inkwash_backgrounds.py → Ink-wash style backgrounds
│ └── generate_chart.py → matplotlib (only for heatmaps/3D/radar; simple charts must use native)
├── assets/
│ └── templates/
│ ├── KimiDocx.csproj → Project file template (for creating new docs)
│ ├── Program.cs → Program entry template
│ ├── Example.cs → Complete example (cover+TOC+charts+back cover)
│ ├── CJKExample.cs → CJK content patterns (quote escaping, fonts)
│ └── xml/ → XML templates for comments infrastructure
└── validator/ → OpenXML validator (pre-compiled binary, AI does not modify)
创建新文档:使用 C# SDK 和 ./scripts/docx build → 查看 Example.cs 了解模式,查看 CJKExample.cs 了解 CJK 内容
编辑现有文档:使用 Python + lxml → 查看 references/EditingGuide.md 获取完整教程
⚠️ 不要混用这两种方法。 创建时使用 C# SDK,编辑时使用 Python。切勿使用 python-docx/docx-js。
环境设置
首次使用时,在 SKILL 目录中执行:
cd /app/.kimi/skills/kimi-docx/
./scripts/docx init
固定路径约定(不可更改):
| 路径 | 用途 |
|---|---|
/app/.kimi/skills/kimi-docx/ | SKILL 目录,命令的执行位置 |
/tmp/docx-work/ | 工作目录,在此处编辑 Program.cs |
/mnt/okcomputer/output/ | 输出目录,最终交付文件存放位置 |
/mnt/okcomputer/upload/ | 用户上传位置(输入文件) |
脚本命令(./scripts/docx <cmd>):
| 命令 | 用途 |
|---|---|
env | 显示环境状态(不做更改) |
init | 设置依赖项和工作区 |
build [out] | 编译、运行、验证(默认:output/output.docx) |
validate FILE | 验证现有 docx |
脚本会自动处理:
- 检测 dotnet/python3(必需)、pandoc/playwright/matplotlib(可选)
- 已安装 → 直接使用;未安装 → 自动安装;故障 → 修复
- 初始化工作目录并复制模板文件
构建流程
必须使用 ./scripts/docx build,不要分别执行 dotnet build && dotnet run(会跳过验证)。
Program.cs 输出路径约定(重要)
Program.cs 必须从命令行参数获取输出路径,否则构建脚本无法找到生成的文件:
// Correct - get output path from command line arguments
string outputFile = args.Length > 0 ? args[0] : "/mnt/okcomputer/output/output.docx";
// Wrong - hardcoded path causes build failure
string outputFile = "my_document.docx"; // Script can't find file!
| 步骤 | 操作 | 备注 |
|---|---|---|
| 1. 编译 | dotnet build | 失败时提供修复建议 |
| 2. 生成 | dotnet run -- <output path> | 通过命令行参数传递路径 |
| 3. 自动修复 | fix_element_order.py | 修复 XML 元素顺序问题 |
| 4. OpenXML 验证 | validator/ | 必须执行 |
| 5. 业务规则 | validate_docx.py | 必须执行 |
| 6. 统计 | 字符数 + 词数 | 可选(需要 pandoc) |
必须进行验证:验证失败时,会保留文件但显示警告。请检查错误消息并修复问题。
独立验证
cd /app/.kimi/skills/kimi-docx/
./scripts/docx validate /mnt/okcomputer/output/report.docx
内容验证(强制)
pandoc 是唯一可信来源。 OpenXML 验证器用于检查结构;pandoc 用于查看实际内容。
交付前,请使用 pandoc 验证:
pandoc output.docx -t plain— 检查文本是否完整- 对于修订/评论:添加
--track-changes=all以验证标记位置
⚠️ 关键提示:comments.xml 存在 ≠ 评论可见。数量不一致 = 未保存 doc_tree。参见 references/EditingGuide.md §5.3。
第 3 部分:质量标准
交付标准
样式通用、审美平庸 = 交付质量平庸。
交付具有工作室级品质的 Word 文档,深入考量内容、功能和样式。用户往往不会明确要求高级功能(封面、目录、背景、封底、脚注、图表)——应深入理解需求并主动扩展。
语言一致性
文档语言 = 用户对话语言(包括文件名、正文、标题、页眉、目录提示、图表标签及所有其他文本)。
页眉和页脚——默认必备
大多数文档必须包含页眉和页脚。具体样式(对齐方式、格式、内容)应与文档整体设计相匹配。
- 页眉:通常为文档标题、公司名称或章节名称
- 页脚:通常为页码(格式不限,如“X / Y”、“第 X 页”、“— X —”等)
- 封面/封底:使用
TitlePage设置隐藏首页上的页眉/页脚
专业元素(关键)
创建超出用户预期的文档,主动添加专业元素,不要等用户提出要求。交付标准:达到 2024 年顶尖设计师的视觉品质。
封面与视觉效果:
- 正式文档(提案、报告、财务文件、投标文件、合同)/创意文档(请柬、贺卡)必须有封面和封底
- 封面必须配有设计师级品质的背景图片
- 正文页可酌情添加背景,以提升视觉吸引力
结构:
- 长文档(3 个或更多章节)应添加目录,并在目录后添加刷新提示
数据呈现:
- 对比数据或展示趋势时,使用图表而非纯文本列表
- 表格使用浅灰色表头或三线表样式,避免使用 Word 默认的蓝色
链接与引用:
- URL 必须是可点击的超链接
- 包含多个图或表时,应添加编号和交叉引用(“见图 1”、“如表 2 所示”)
- 学术/法律/数据分析类引用场景,应实现正确的文内点击跳转引用,并添加对应的脚注/尾注
目录刷新提示
Word 目录是域代码,生成时页码可能不准确。必须在目录后添加灰色提示文本,告知用户手动刷新:
Table of Contents
─────────────────
Chapter 1 Overview .......................... 1
Chapter 2 Methods ........................... 3
...
(Hint: On first open, right-click the TOC and select "Update Field" to show correct page numbers)
提示文本要求:
- 视觉上应较为低调——使用灰色和较小字号,不应喧宾夺主,影响目录条目阅读
- 语言:与用户对话语言一致
仅在用户明确要求时
| 功能 | 原因 |
|---|---|
| 水印 | 会改变视觉状态。SDK 限制:VML 水印类无法正确序列化;必须向页眉写入原始 XML。 |
| 文档保护 | 限制编辑 |
| 邮件合并字段 | 需要数据源 |
图表选择策略(关键)
默认使用 Word 原生图表,可编辑、文件体积小且专业。
| 图表类型 | 方法 | 备注 |
|---|---|---|
| 饼图 | 原生 | Example.cs → AddPieChart() |
| 柱状图 | 原生 | Example.cs → AddBarChart() |
| 折线图 | 原生 | 参考柱状图结构,使用 c:lineChart |
| 横向条形图 | 原生 | 参考柱状图结构,使用 barDir="bar" |
| 热力图、3D 图、雷达图 | matplotlib | Word 原生不支持 |
| 复杂统计图(箱线图等) | matplotlib | Word 原生不支持 |
优先使用原生图表(可编辑、文件更小),但在数据分析场景中也可使用 matplotlib。
插入图片/图表
任何 PNG(matplotlib 图表、背景、照片)都必须使用 AddInlineImage() 插入:
AddInlineImage(body, mainPart, "/path/to/image.png", "Description", docPrId++);
关键事项:
- 图表标签/标题必须与文档语言一致(例如,中文文档使用中文标签)
- 构建输出会显示
X images——如果为 0,则表示未插入图片
内容限制
字数/页数要求
| 用户请求 | 执行标准 |
|---|---|
| 指定字数(例如,“3000 字”) | 实际输出控制在 ±20% 以内 |
| 指定页数(例如,“5 页”) | 精确匹配 |
| 字数范围(例如,“2000-3000 字”) | 在范围内 |
| 最低字数(例如,“至少 5000 字”) | 不超过要求的 2 倍 |
禁止:使用过多的项目符号列表来凑字数。保持信息密度。
遵循大纲
- 用户提供大纲:严格遵循,不得增删或调整顺序
- 未提供大纲:使用标准结构
- 学术:引言 → 文献 → 方法 → 结果 → 讨论 → 结论
- 商务:执行摘要 → 分析 → 建议
- 技术:概述 → 原则 → 用法 → 示例 → 常见问题
场景完整性
提前考虑用户的下一步需求,补全场景所需的要素。以下示例并不全面——请将此原则应用于所有文档类型:
- 试卷 → 姓名/班级/学号填写栏、每题分值(考虑总分)、评分栏
- 合同 → 双方签字和盖章处、日期、合同编号、附件清单
- 会议纪要 → 出席人员、缺席人员、责任人明确的待办事项、下次会议时间
设计理念
配色方案
使用低饱和度色调,避免使用 Word 默认蓝色和 matplotlib 默认高饱和度色彩。
根据文档场景灵活选择配色方案:
| 风格 | 配色 | 适用场景 |
|---|---|---|
| 莫兰迪 | 柔和、低饱和度色调 | 艺术、编辑出版 |
| 大地色系 | 棕色、橄榄色、自然色 | 环保、有机 |
| 北欧风 | 冷灰、雾蓝 | 极简、科技 |
| 日式侘寂 | 灰色、原木色、禅意色 | 传统、沉思 |
| 法式优雅 | 米白、灰粉 | 奢华、女性化 |
| 工业风 | 炭灰、铁锈色、混凝土色 | 制造、工程 |
| 学术风 | 海军蓝、酒红、象牙白 | 研究、教育 |
| 海洋雾色 | 雾蓝、沙色 | 海洋、健康 |
| 森林苔藓 | 橄榄色、苔藓绿 | 自然、可持续发展 |
| 沙漠暮色 | 赭黄、沙金色 | 温暖、地域特色 |
同一文档中的配色方案必须保持一致。
布局
留白(页边距、段落间距),层次清晰(H1 > H2 > 正文),内边距适当(文本不应贴着边框)。
分页控制
Word 使用流式布局,而不是固定分页。通过以下属性控制分页:
| 属性 | XML | 效果 |
|---|---|---|
| 与下段同页 | <w:keepNext/> | 标题与后续段落保持在同一页 |
| 段中不分页 | <w:keepLines/> | 段落不会跨页拆分 |
| 段前分页 | <w:pageBreakBefore/> | 强制新起一页(用于 H1) |
| 孤行控制 | <w:widowControl/> | 避免页面顶部或底部出现孤行 |
// Example: H1 always starts on new page, stays with next paragraph
new ParagraphProperties(
new ParagraphStyleId { Val = "Heading1" },
new PageBreakBefore(),
new KeepNext(),
new KeepLines()
)
表格分页:
// Allow row to break across pages (avoid large blank areas)
new TableRowProperties(
new CantSplit { Val = false } // false = can split
)
// Repeat header row on each page
new TableRowProperties(
new TableHeader()
)
第 4 部分:技术参考
选择适合的路径:
| 任务 | 技术栈 | 参考资料 |
|---|---|---|
| 创建新文档 | C# + OpenXML SDK | 4.1-4.6 + Example.cs |
| 编辑现有文档 | Python + lxml | 4.7 + references/EditingGuide.md |
4.1 SDK 基础知识
架构合规(请牢记)
OpenXML 对元素顺序有严格要求。顺序错误 = Word 无法打开文件。
必需样式
// Normal style must exist - all Heading styles use basedOn="Normal"
styles.Append(new Style(
new StyleName { Val = "Normal" },
new StyleParagraphProperties(
new SpacingBetweenLines { After = "200", Line = "276", LineRule = LineSpacingRuleValues.Auto }
),
new StyleRunProperties(
new RunFonts { Ascii = "Calibri", HighAnsi = "Calibri" },
new FontSize { Val = "22" },
new FontSizeComplexScript { Val = "22" }
)
) { Type = StyleValues.Paragraph, StyleId = "Normal", Default = true });
元素顺序规则
大多数顺序问题都会由 fix_element_order.py 自动修复。请记住以下关键规则:
| 父元素 | 关键规则 |
|---|---|
sectPr | headerRef → footerRef 必须位于 pgSz → pgMar 之前 |
Table | 必须在 tblPr 和 tr 之间包含 tblGrid(见下文) |
表格必须包含 tblGrid
// Correct - table must define grid
var table = new Table();
table.Append(new TableProperties(...));
table.Append(new TableGrid( // Required!
new GridColumn { Width = "4680" },
new GridColumn { Width = "4680" }
));
table.Append(new TableRow(...));
// Wrong - missing tblGrid, Word cannot open
var table = new Table();
table.Append(new TableProperties(...));
table.Append(new TableRow(...)); // Adding rows directly
表格列宽一致性
表格歪斜的主要原因:tblGrid 中的 gridCol 宽度与单元格的 tcW 宽度不匹配。
// Correct - gridCol and tcW match exactly
table.Append(new TableGrid(
new GridColumn { Width = "3600" }, // First column
new GridColumn { Width = "5400" } // Second column
));
var row = new TableRow(
new TableCell(
new TableCellProperties(
new TableCellWidth { Width = "3600", Type = TableWidthUnitValues.Dxa } // Matches gridCol!
),
new Paragraph(new Run(new Text("Content")))
),
new TableCell(
new TableCellProperties(
new TableCellWidth { Width = "5400", Type = TableWidthUnitValues.Dxa } // Matches gridCol!
),
new Paragraph(new Run(new Text("Content")))
)
);
| 规则 | 原因 |
|---|---|
| gridCol 数量 = 表格列数 | 否则列宽计算会失败 |
| gridCol.Width = tcW.Width | 不匹配会导致表格歪斜(验证时会检查) |
| 同一列中的所有行使用相同的 tcW | 保持列宽一致 |
值限制
paraId必须小于0x80000000(用于批注段落 ID)
创建与编辑
| 任务 | 方法 | 原因 |
|---|---|---|
| 创建新文档 | C# OpenXML SDK | 自动处理包结构、rels 和 Content_Types |
| 编辑现有文档 | Python + lxml | 透明、无黑盒且可完全控制 |
创建新文档:使用 SDK 编写 Example.cs 模式。
编辑现有文档:完整的 Python 工作流请参阅 references/EditingGuide.md。
Example.cs
请阅读整个文件以了解总体结构,而不只是单个函数。该文件展示了各个部分如何衔接(封面 → 目录 → 正文 → 封底)。
Example 中的“Project Proposal”“[Company Name]”等内容仅为示例内容,配色方案也仅供参考。
| 要了解的内容 | 不要学习的内容 |
|---|---|
| 章节划分(封面 → 目录 → 正文 → 封底) | 具体配色值 |
| 浮动背景插入代码 | 示例中的业务内容 |
| 图表创建 API 调用 | 示例中的文案 |
| 样式定义结构 | 示例中的硬编码数据 |
⚠️ **不要照搬 Example 的配色方案。**请像顶尖设计师一样,根据文档场景重新设计视觉样式。
函数索引(请阅读源代码了解实现细节):
| 功能 | 函数 | 行号 |
|---|---|---|
| 文档结构 | ||
| 样式(Normal、Heading1-3) | AddStyles() | 85-203 |
| 封面页 | AddCoverSection() | 369-453 |
| 目录 | AddTocSection() | 458-526 |
| 正文部分 | AddContentSection() | 531-729 |
| 封底 | AddBackcoverSection() | 734-794 |
| 视觉元素 | ||
| 浮动背景 | CreateFloatingBackground() | 228-279 |
| 保持比例的嵌入式图片 | AddInlineImage() | 285-364 |
| 表格 | ||
| 三线表 | CreateDataTable() | 853-888 |
| 表头行(灰色背景) | CreateSimpleHeaderRow() | 933-971 |
| 数据行 | CreateSimpleDataRow() | 976-1008 |
| 图表 | ||
| 饼图 | AddPieChart() | 1013-1049 |
| 柱状图 | AddBarChart() | 1133-1169 |
| 页面元素 | ||
| 带背景的页眉 | 位于 AddContentSection() 中 | 534-575 |
| 带页码的页脚 | 位于 AddContentSection() 中 | 578-588 |
| 页码字段 | CreatePageNumberField() | 1345-1354 |
| 总页数域 | CreateTotalPagesField() | 1356-1365 |
| 高级功能 | ||
| 脚注 | AddFootnote() | 1370-1410 |
| 交叉引用 | CreateCrossReference() | 1415-1425 |
| 编号/列表 | CreateBasicNumbering() | 1327-1340 |
CJKExample.cs
CJK 文档只能阅读 CJKExample.cs——如果改为阅读 Example.cs,会导致错误(缺少字体配置、引号转义)。它处理以下内容:
- 引号转义(
""→\u201c\u201d) - CJK 字体配置(SimHei、Microsoft YaHei)
- CJK 文本的段落缩进
其结构与 Example.cs 完全相同,无需同时阅读两个文件。
4.2 内容元素
域代码
PAGE/NUMPAGES/DATE/TOC — 结构:FieldChar(Begin) → FieldCode(" PAGE ") → FieldChar(Separate) → Text → FieldChar(End)。结果会缓存;WPS 不支持 UpdateFieldsOnOpen。
书签和交叉引用
书签用于标记位置(BookmarkStart/BookmarkEnd 使用匹配的 ID);交叉引用通过 REF 域链接(" REF bookmarkName \\h ")。
注意事项:删除带书签的文本会同时删除书签 → “Error! Reference source not found”。
4.3 视觉设计
背景图片设计
封面/封底必须有背景。背景图片中央应留白,并使用低饱和度的颜色。背景图片中不得包含任何文字;文字应在 Word 中添加,以便用户编辑。
设计流程
- 阅读示例:阅读
scripts/generate_backgrounds.py,了解 HTML/CSS 技巧(radial-gradient、transparency、positioning) - 选择方向:根据文档场景,从下表中选择一种风格方向
- 原创设计:从头编写新的 HTML/CSS——示例展示的是一种风格,你的设计应有所不同
⚠️ 照搬示例 = 所有文档看起来都一样 = 交付质量平庸。 每份文档都应有独特的视觉标识,并与其内容和用途相匹配。
风格参考
| 风格 | 关键元素 | 适用场景 |
|---|---|---|
| MUJI | 细边框 + 留白 | 极简、日式、生活方式 |
| Bauhaus | 分散的几何形状 | 艺术、设计、创意 |
| Swiss Style | 网格线 + 强调条 | 专业、企业 |
| Soft Blocks | 柔和色块矩形、透明叠加 | 温馨、教育、医疗 |
| Rounded Geometry | 圆角矩形、胶囊形状 | 科技、互联网、年轻化 |
| Frosted Glass | 模糊 + 透明 + 细腻边框 | 现代、高端、科技 |
| Gradient Ribbons | 柔和渐变椭圆 + 小圆点 | 女性、 beauty、柔和 |
| Dot Matrix | 规则的点阵纹理 | 技术、数据、工程 |
| Double Border | 嵌套边框 + 角落装饰 | 传统、正式、法律 |
| Waves | 底部 SVG 波浪 + 渐变背景 | 海洋、环保、流动感 |
| Warm Natural | 大地色调 + 有机形状 | 环保、农业、自然 |
技术说明:Playwright 以 794×1123px 生成图像(device_scale_factor=2),并以浮动锚点形式插入,设置 BehindDoc=true。参见 Example.cs:CreateFloatingBackground()。
信笺抬头(商务文档)
对于正式商务信函,可考虑在页眉区域添加信笺抬头。常见模式:
- 仅在首页使用完整信笺抬头(徽标 + 公司名称 + 联系信息),后续页面简化或隐藏
- 在
SectionProperties中使用TitlePage,启用不同的首页页眉 - 根据具体业务场景灵活设计——没有固定规则
双栏布局
使用带有 Columns 的 sectPr。该设置会影响整个节,直到下一个 sectPr。
4.4 特殊内容
数学公式(OMML)
核心模式:<m:e> 是通用内容容器。几乎所有元素都会将内容封装在 <m:e> 中。
文本:始终使用 <m:r><m:t>text</m:t></m:r>,绝不使用裸文本。
根元素:<m:oMath>(行内)或 <m:oMathPara>(显示)。不要在一个 <m:oMath> 内嵌套另一个。
结构示例:
| 元素 | 结构 |
|---|---|
| 分数 | <m:f><m:num><m:e>…</m:e></m:num><m:den><m:e>…</m:e></m:den></m:f> |
| 下标 | <m:sSub><m:e>base</m:e><m:sub><m:e>…</m:e></m:sub></m:sSub> |
| 上标 | <m:sSup><m:e>base</m:e><m:sup><m:e>…</m:e></m:sup></m:sSup> |
| 根式 | <m:rad><m:deg><m:e>n</m:e></m:deg><m:e>radicand</m:e></m:rad> |
| 矩阵 | <m:m><m:mr><m:e>cell</m:e><m:e>cell</m:e></m:mr></m:m> |
| 多元运算符(∑∫) | <m:nary><m:sub><m:e>…</m:e></m:sub><m:sup><m:e>…</m:e></m:sup><m:e>body</m:e></m:nary> |
| 定界符 | <m:d><m:dPr><m:begChr m:val="("/><m:endChr m:val=")"/></m:dPr><m:e>…</m:e></m:d> |
| 方程组 | <m:eqArr><m:e>eq1</m:e><m:e>eq2</m:e></m:eqArr> |
易错点:矩阵单元格使用 <m:e>,而不是用于列属性的 <m:mc>。
C# 字符串中的弯引号
C# 会将 " " 视为字符串定界符 → CS1003。最简单的修复方法:在字符串字面量中使用转义的直引号 \"。如果必须使用弯引号,请使用 XML 实体编码:“ ”(双引号)或 ‘ ’(单引号)。
中文引号处理——完整模式请参阅 CJKExample.cs:
// ❌ Wrong - Chinese quotes break compilation
new Text("请点击"确定"按钮") // CS1003!
// ✓ Correct - use Unicode escapes
new Text("请点击\u201c确定\u201d按钮")
| 字符 | Unicode | 用法 |
|---|---|---|
| "(左双引号) | \u201c | 开始引号 |
| "(右双引号) | \u201d | 结束引号 |
| '(左单引号) | \u2018 | 开始单引号 |
| '(右单引号) | \u2019 | 结束单引号 |
⚠️ 不要使用逐字字符串 @""——\u 转义在逐字字符串中不起作用:
// ❌ WRONG - @"" verbatim string, \u NOT escaped, outputs literal "\u201c"
string text = @"她说\u201c你好\u201d"; // Outputs: 她说\u201c你好\u201d
// ✓ CORRECT - regular string, \u IS escaped
string text = "她说\u201c你好\u201d"; // Outputs: 她说"你好"
// ✓ For long text, use + concatenation
string para = "第一段内容," +
"她说\u201c这是引用\u201d," +
"继续写第二段。";
单位
Twip = 1/20 pt(11906 = A4 纸张宽度)。字号使用半磅为单位(24 = 12pt)。EMU = 914400/英寸。
4.5 页面布局
图像大小
wp:extent 和 a:ext 的 Cx/Cy 必须一致。按比例缩放时:读取 PNG 文件头(字节 16-23)获取尺寸,并计算 cy = cx * height / width。
分页控制
为标题/图表段落添加 KeepNext,以避免标题孤行或图表与题注分离。
分节符
pPr 中的 sectPr = 节的最后一个段落。避免同时使用 PageBreak 和 Continuous(会出现空白页)。请使用 NextPage。
目录(TOC)
WPS 不支持 UpdateFieldsOnOpen → 必须使用域代码结构预先填充目录条目:FieldChar(Begin) → FieldCode(" TOC ...") → FieldChar(Separate) → 占位条目(带超链接的文本 + 页码)→ FieldChar(End)。Separate 和 End 之间的占位条目可让 Word 立即显示目录;用户刷新后可获得准确页码。绝不要使用静态文本段落模拟目录——必须使用域代码结构,否则无法刷新。参阅 Example.cs:AddTocSection()。
参数:\o "1-3"(标题级别)、\h(超链接)、\z(在 Web 视图中隐藏页码)、\u(大纲级别)。
标题必须使用内置的 Heading1/Heading2 样式(无法识别自定义样式)。
对齐和排版
CJK 正文:两端对齐 + 2 字符缩进。英文:左对齐。表格数字:右对齐。标题:无缩进。
4.6 页面元素
页眉和页脚
// 1. Create header part
var headerPart = mainPart.AddNewPart<HeaderPart>();
var headerId = mainPart.GetIdOfPart(headerPart);
headerPart.Header = new Header(
new Paragraph(
new ParagraphProperties(
new ParagraphStyleId { Val = "Header" },
new Justification { Val = JustificationValues.Center }
),
new Run(new Text("Document Title"))
)
);
// 2. Create footer part (with page numbers)
var footerPart = mainPart.AddNewPart<FooterPart>();
var footerId = mainPart.GetIdOfPart(footerPart);
var footerPara = new Paragraph(
new ParagraphProperties(
new Justification { Val = JustificationValues.Center }
)
);
// PAGE field: Begin → FieldCode → Separate → Text → End
footerPara.Append(new Run(new FieldChar { FieldCharType = FieldCharValues.Begin }));
footerPara.Append(new Run(new FieldCode(" PAGE ")));
footerPara.Append(new Run(new FieldChar { FieldCharType = FieldCharValues.Separate }));
footerPara.Append(new Run(new Text("1"))); // Placeholder, updated on open
footerPara.Append(new Run(new FieldChar { FieldCharType = FieldCharValues.End }));
footerPara.Append(new Run(new Text(" / ") { Space = SpaceProcessingModeValues.Preserve }));
// NUMPAGES field (same structure)
footerPara.Append(new Run(new FieldChar { FieldCharType = FieldCharValues.Begin }));
footerPara.Append(new Run(new FieldCode(" NUMPAGES ")));
footerPara.Append(new Run(new FieldChar { FieldCharType = FieldCharValues.Separate }));
footerPara.Append(new Run(new Text("1")));
footerPara.Append(new Run(new FieldChar { FieldCharType = FieldCharValues.End }));
footerPart.Footer = new Footer(footerPara);
// 3. Reference in SectionProperties
new SectionProperties(
new HeaderReference { Type = HeaderFooterValues.Default, Id = headerId },
new FooterReference { Type = HeaderFooterValues.Default, Id = footerId },
new PageSize { Width = 11906, Height = 16838 },
new PageMargin { Top = 1440, Right = 1440, Bottom = 1440, Left = 1440, Header = 720, Footer = 720 }
)
页眉/页脚类型:
| 类型 | HeaderFooterValues | 用途 |
|---|---|---|
| 默认 | .Default | 奇数页(或所有页面) |
| 偶数页 | .Even | 偶数页 |
| 首页 | .First | 首页 |
首页不同(用于封面):在 sectPr 中添加 TitlePage()。
奇偶页不同:在 settings.xml 中添加 <w:evenAndOddHeaders/>。
脚注和尾注
分隔符易错点:FootnotesPart/EndnotesPart 必须在任何用户注释之前包含 Id=-1(Separator)和 Id=0(ContinuationSeparator)。缺少这些内容 → Word 将无法渲染。
<w:footnote w:type="separator" w:id="-1">
<w:p><w:r><w:separator/></w:r></w:p>
</w:footnote>
<w:footnote w:type="continuationSeparator" w:id="0">
<w:p><w:r><w:continuationSeparator/></w:r></w:p>
</w:footnote>
列表
需要 NumberingDefinitionsPart,其中包含 AbstractNum 和 NumberingInstance。在段落中通过 NumberingProperties 应用。
多级列表:创建包含多个 Level 的 AbstractNum。格式:Decimal、UpperLetter、LowerRoman、Bullet、ChineseCounting。
超链接
必须使用 <w:hyperlink> 元素,不能使用纯文本。 需要先创建关系:
var relId = mainPart.AddHyperlinkRelationship(new Uri("https://example.com"), true).Id;
paragraph.Append(new Hyperlink(new Run(
new RunProperties(new Color { Val = "0563C1" }, new Underline { Val = UnderlineValues.Single }),
new Text("Click here")
)) { Id = relId })
图表与可视化
| 要求 | 首选方案 | 替代方案 |
|---|---|---|
| 数据图表 | Word 原生 | matplotlib PNG |
| 流程图 | DrawingML Shapes | 表格布局 |
| 插图 | 图像生成 | 图像搜索 |
Word 图表:使用 NumberLiteral(无需 Excel),使用 DataPoint 设置颜色。请参阅示例。
matplotlib:使用 dpi=300、axes.unicode_minus=False。字体和标签必须与文档语言一致。
4.7 编辑操作(Python API)
使用 docx_lib.editing 添加批注和跟踪更改:
from scripts.docx_lib.editing import (
DocxContext,
add_comment, reply_comment, resolve_comment, delete_comment,
insert_paragraph, insert_text, propose_deletion,
reject_insertion, restore_deletion, enable_track_changes
)
with DocxContext("input.docx", "output.docx") as ctx:
# add_comment(ctx, para_text, comment, highlight=None)
# - para_text: text to locate paragraph
# - comment: comment content
# - highlight: text to highlight (omit to highlight entire paragraph)
add_comment(ctx, "M-SVI index", "Please define", highlight="M-SVI")
insert_text(ctx, "The method", after="method", new_text=" and materials")
完整指南:references/EditingGuide.md
4.8 XML 速查
文本格式(rPr)
<w:r>
<w:rPr>
<w:rFonts w:ascii="Times New Roman" w:eastAsia="SimSun"/>
<w:sz w:val="24"/>
<w:b/><w:i/><w:u w:val="single"/>
<w:color w:val="FF0000"/>
</w:rPr>
<w:t>text</w:t>
</w:r>
字号:21=10.5pt、24=12pt、28=14pt、32=16pt、44=22pt
跟踪更改结构
<w:ins w:id="1" w:author="..." w:date="...">
<w:r><w:rPr>...</w:rPr><w:t>text</w:t></w:r>
</w:ins>
<w:del w:id="2" w:author="..." w:date="...">
<w:r><w:rPr>...</w:rPr><w:delText>text</w:delText></w:r>
</w:del>
要点:<w:ins> 和 <w:del> 都要包裹 <w:r>,而不是放在其中。删除内容应使用 <w:delText>,而不是 <w:t>。
架构约束
| 规则 | 要求 |
|---|---|
| RSID 值 | 8 位大写十六进制:00A1B2C3 |
| 空白字符 | 对前导/尾随空格使用 xml:space="preserve" |
| 修订结构 | <w:ins>/<w:del> 包裹 <w:r>,且必须具有 w:id 属性 |
完整示例:完整可运行代码请参阅 references/EditingGuide.md。