docx

SKILL.md

DOCX 创建、编辑与分析

概述

.docx 文件是包含 XML 文件的 ZIP 归档。处理方式取决于任务类型:

任务 方法
读取/分析内容 使用项目内置 read_document 工具
创建新文档 使用项目内置 create_document 工具(推荐),或 docx-js
编辑现有文档 使用项目内置 edit_document 工具(推荐),或解包→编辑XML→重打包

重要: 本项目已内置 create_documentedit_documentread_document 工具,优先使用这些工具。以下 docx-js 和 XML 编辑指南作为高级参考,用于工具无法满足的复杂场景。

使用内置工具(推荐)

创建 Word 文档

<create_document>
<type>word</type>
<file_path>/path/to/output.docx</file_path>
<document_data>{"title":"报告标题","subtitle":"副标题","sections":[{"heading":"第一章","paragraphs":["段落内容",{"text":"加粗文本","bold":true}],"table":[["列1","列2"],["数据1","数据2"]]}]}</document_data>
<options>{"template":"none"}</options>
</create_document>

注意: type 必须是 "word"(不是 "docx")。学术论文默认使用 template:"ieee_bilingual"

读取 Word 文档

<read_document>
<uri>/path/to/doc.docx</uri>
</read_document>

编辑现有 Word 文档(增量替换,保留格式)

<edit_document>
<uri>/path/to/doc.docx</uri>
<content></content>
<replacements>[{"find":"旧文本","replace":"新文本","bold":true}]</replacements>
</edit_document>

转换格式

<document_convert>
<input_file>/path/to/doc.docx</input_file>
<output_path>/path/to/doc.pdf</output_path>
<format>pdf</format>
</document_convert>

高级:使用 docx-js 创建文档

当内置工具无法满足需求时(如需要精确控制 XML 结构),可使用 docx-js:

基础设置

const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun,
        Header, Footer, AlignmentType, PageOrientation, LevelFormat, ExternalHyperlink,
        InternalHyperlink, Bookmark, FootnoteReferenceRun, PositionalTab,
        PositionalTabAlignment, PositionalTabRelativeTo, PositionalTabLeader,
        TabStopType, TabStopPosition, Column, SectionType,
        TableOfContents, HeadingLevel, BorderStyle, WidthType, ShadingType,
        VerticalAlign, PageNumber, PageBreak } = require('docx');

const doc = new Document({ sections: [{ children: [/* content */] }] });
Packer.toBuffer(doc).then(buffer => fs.writeFileSync("doc.docx", buffer));

页面尺寸

// docx-js 默认 A4,需显式设置
sections: [{
  properties: {
    page: {
      size: {
        width: 12240,   // 8.5 英寸 (DXA单位)
        height: 15840   // 11 英寸
      },
      margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } // 1英寸边距
    }
  },
  children: [/* content */]
}]

常用页面尺寸 (DXA 单位, 1440 DXA = 1 英寸):

纸张 宽度 高度 内容宽度(1英寸边距)
US Letter 12,240 15,840 9,360
A4 (默认) 11,906 16,838 9,026

样式(覆盖内置标题)

const doc = new Document({
  styles: {
    default: { document: { run: { font: "Arial", size: 24 } } }, // 12pt 默认
    paragraphStyles: [
      { id: "Heading1", name: "Heading 1", basedOn: "Normal", next: "Normal", quickFormat: true,
        run: { size: 32, bold: true, font: "Arial" },
        paragraph: { spacing: { before: 240, after: 240 }, outlineLevel: 0 } },
      { id: "Heading2", name: "Heading 2", basedOn: "Normal", next: "Normal", quickFormat: true,
        run: { size: 28, bold: true, font: "Arial" },
        paragraph: { spacing: { before: 180, after: 180 }, outlineLevel: 1 } },
    ]
  },
  sections: [{
    children: [
      new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun("标题")] }),
    ]
  }]
});

列表(禁止使用 Unicode 符号)

// ❌ 错误 - 不要手动插入符号
new Paragraph({ children: [new TextRun("• 项目")] })  // 错误

// ✅ 正确 - 使用 numbering 配置
const doc = new Document({
  numbering: {
    config: [
      { reference: "bullets",
        levels: [{ level: 0, format: LevelFormat.BULLET, text: "•", alignment: AlignmentType.LEFT,
          style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
      { reference: "numbers",
        levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1.", alignment: AlignmentType.LEFT,
          style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
    ]
  },
  sections: [{
    children: [
      new Paragraph({ numbering: { reference: "bullets", level: 0 },
        children: [new TextRun("无序项")] }),
      new Paragraph({ numbering: { reference: "numbers", level: 0 },
        children: [new TextRun("有序项")] }),
    ]
  }]
});

表格

// 关键:表格需要双重宽度设置 - table.columnWidths + cell.width
const border = { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" };
const borders = { top: border, bottom: border, left: border, right: border };

new Table({
  width: { size: 9360, type: WidthType.DXA }, // 始终用 DXA(百分比在 Google Docs 中异常)
  columnWidths: [4680, 4680], // 必须等于表格宽度
  rows: [
    new TableRow({
      children: [
        new TableCell({
          borders,
          width: { size: 4680, type: WidthType.DXA },
          shading: { fill: "D5E8F0", type: ShadingType.CLEAR }, // 用 CLEAR 不用 SOLID
          margins: { top: 80, bottom: 80, left: 120, right: 120 },
          children: [new Paragraph({ children: [new TextRun("单元格")] })]
        })
      ]
    })
  ]
})

图片

new Paragraph({
  children: [new ImageRun({
    type: "png", // 必须:png, jpg, jpeg, gif, bmp, svg
    data: fs.readFileSync("image.png"),
    transformation: { width: 200, height: 150 },
    altText: { title: "标题", description: "描述", name: "名称" }
  })]
})

页眉/页脚/页码

sections: [{
  headers: {
    default: new Header({ children: [new Paragraph({ children: [new TextRun("页眉")] })] })
  },
  footers: {
    default: new Footer({ children: [new Paragraph({
      children: [new TextRun("第 "), new TextRun({ children: [PageNumber.CURRENT] }), new TextRun(" 页")]
    })] })
  },
  children: [/* content */]
}]

目录

// 标题必须使用 HeadingLevel,不能用自定义样式
new TableOfContents("目录", { hyperlink: true, headingStyleRange: "1-3" })

超链接

// 外部链接
new Paragraph({
  children: [new ExternalHyperlink({
    children: [new TextRun({ text: "点击这里", style: "Hyperlink" })],
    link: "https://example.com",
  })]
})

// 内部书签链接
new Paragraph({ heading: HeadingLevel.HEADING_1, children: [
  new Bookmark({ id: "chapter1", children: [new TextRun("第一章")] }),
]})
new Paragraph({ children: [new InternalHyperlink({
  children: [new TextRun({ text: "见第一章", style: "Hyperlink" })],
  anchor: "chapter1",
})]})

docx-js 关键规则

  • 显式设置页面尺寸 — 默认 A4,中国文档建议 A4(11906×16838)
  • 横向:传入纵向尺寸 — docx-js 内部交换宽高
  • 禁止 \n — 用独立 Paragraph
  • 禁止 Unicode 符号 — 用 LevelFormat.BULLET
  • PageBreak 必须在 Paragraph 内
  • ImageRun 必须指定 type
  • 表格始终用 WidthType.DXA — 百分比在 Google Docs 中异常
  • 表格双重宽度columnWidths + 每个 cell 的 width 必须匹配
  • ShadingType.CLEAR — SOLID 会导致黑色背景
  • 不要用表格做分隔线 — 用 Paragraph 的 border 属性
  • TOC 要求 HeadingLevel — 不能用自定义样式
  • 覆盖内置样式 — 使用精确 ID: "Heading1"、"Heading2" 等
  • 包含 outlineLevel — TOC 必需(H1=0, H2=1...)

高级:编辑现有文档(XML 方式)

当需要精确控制跟踪修改/批注等高级功能时:

步骤 1:解包

python scripts/office/unpack.py document.docx unpacked/

步骤 2:编辑 XML

编辑 unpacked/word/ 中的文件。使用智能引号 XML 实体:

实体 字符
&#x2018; ' (左单引号)
&#x2019; ' (右单引号/撇号)
&#x201C; " (左双引号)
&#x201D; " (右双引号)

步骤 3:重打包

python scripts/office/pack.py unpacked/ output.docx --original document.docx

跟踪修改 XML 参考

插入:

<w:ins w:id="1" w:author="SenWeaver" w:date="2025-01-01T00:00:00Z">
  <w:r><w:t>插入的文本</w:t></w:r>
</w:ins>

删除:

<w:del w:id="2" w:author="SenWeaver" w:date="2025-01-01T00:00:00Z">
  <w:r><w:delText>删除的文本</w:delText></w:r>
</w:del>

最小化编辑 — 只标记变化部分:

<w:r><w:t>期限为 </w:t></w:r>
<w:del w:id="1" w:author="SenWeaver" w:date="...">
  <w:r><w:delText>30</w:delText></w:r>
</w:del>
<w:ins w:id="2" w:author="SenWeaver" w:date="...">
  <w:r><w:t>60</w:t></w:r>
</w:ins>
<w:r><w:t> 天。</w:t></w:r>
Weekly Installs
2
GitHub Stars
15
First Seen
10 days ago
Installed on
cline2
gemini-cli2
github-copilot2
codex2
kimi-cli2
cursor2