关于 officecli-docx
officecli-docx 是指导 Agent 使用 officecli 创建、读取和编辑 DOCX 文档的技能,面向需要制作或检查 Word 文档的工作流。它强调先查 CLI 帮助、逐步执行修改,并通过结构、文本和 HTML 视图进行质量检查。
主要功能
- 01创建和编辑 DOCX 内容与结构
- 02用语义路径读取并修改元素
- 03通过查询和视图检查文档
- 04遵循格式层级与排版规范
- 05逐步执行并验证每项修改
适用场景
- 01从头制作格式清晰的报告
- 02检查并修改已有 DOCX 文档
- 03查找空段落、格式问题或缺失替代文本
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ iofficeai/ officecli --skill officecli-docx安装后在 Claude Code 中输入/officecli-docx确认已加载。
详细介绍
OfficeCLI DOCX 技能
设置
如果缺少 officecli:
- macOS / Linux:
curl -fsSL https://d.officecli.ai/install.sh | bash - Windows (PowerShell):
irm https://d.officecli.ai/install.ps1 | iex
使用 officecli --version 验证(如果 PATH 尚未更新,请打开新的终端)。如果安装失败,请从 https://github.com/iOfficeAI/OfficeCLI/releases 下载二进制文件。
⚠️ 先查帮助规则
本技能介绍优质 docx 的特点,而非每个命令标志的用法。如果不确定属性名称、枚举值或别名,请先查阅帮助,再进行猜测。
officecli help docx # List all docx elements
officecli help docx <element> # Full element schema (e.g. paragraph, field, numbering, watermark, toc)
officecli help docx <verb> <element> # Verb-scoped (e.g. add field, set section)
officecli help docx <element> --json # Machine-readable schema
帮助内容与已安装的 CLI 版本绑定。如果本技能与帮助内容不一致,以帮助内容为准。
思维模型
.docx 是一个包含 XML 部件的 ZIP 文件(document.xml、styles.xml、numbering.xml、header*.xml、footer*.xml、comments.xml,……)。用户看到的一切内容——标题、表格、页码、目录、修订——都是该 ZIP 文件中的 XML。officecli 提供了一个语义路径 API(/body/p[1]/r[2]),因此你几乎不必接触原始 XML;必须操作原始 XML 时,请使用 raw-set(见 XML 附录)。
Shell 与执行规范
docx 路径包含 [];一些属性值包含 $。两者都是 Shell 元字符。转义分为三个层次——请分别处理。
- Shell。 始终为元素路径加引号:
"/body/p[1]",不要写成/body/p[1](zsh/bash 会将[N]视为通配符)。包含$的值一律使用单引号:--prop text='$50M'——无论值有多长,整个值都要放在一对单引号内。未加引号的$50M会被截掉,只剩下M;在一个长字符串中混用'…$var…'和"…$50…",就会导致$50悄悄消失。 - CLI(
text=)。--prop text=会解析两个字符的转义序列\n、\v和\t(规则与 pptx 相同):\n会开始新段落(每个新<w:p>都会继承源段落的样式),\v是同一段落内的软换行(<w:br/>),\t表示<w:tab/>。将反斜杠加倍(\\n)可表示字面量反斜杠-n(通常很少需要)。行级表格快捷方式c1…cN是例外:其中的\n表示单元格内的<w:br/>换行(见配方 (e))。 - JSON(批处理)。 批处理不会解析两个字符的转义序列——JSON
"\\n"或"\\v"会作为字面文本写入。要表示实际字符,请使用 JSON 转义:"\n"(换行)会开始新段落,"\u000b"是软换行。
如有疑问,写入后运行 view text,逐字符比对。
增量执行。 officecli 每次调用都会修改文件。请逐条运行命令,并检查每条命令的退出码——包含 50 条命令的脚本若在第 3 条失败,之后的错误会悄然连锁发生。每次结构操作(新样式、表格、目录、分节符)后,都先对其运行 get,再继续操作。
打开/保存生命周期: 开始时运行 officecli open <file>,最后运行 officecli save <file>,将更改写入磁盘——save 只负责写入,并让常驻进程保持就绪,以便后续编辑;只有在一次性交接时,才使用 officecli close <file> 释放常驻进程。两者始终安全(不会报错或丢失工作)。对于多个使用同一样式的段落,请使用 batch(一次处理整个数组)。仅在跨出 officecli 的边界时刷新: officecli 自身的读取始终能看到你的更改;只有在非 officecli 程序要读取文件之前(例如 python-docx、Word、渲染器或交付)才运行 save/close。
$FILE 约定。 所有命令都使用 "$FILE"——设置一次即可(FILE="your-doc.docx")。不要将字面量 doc.docx / review.docx 直接复制到输出中——务必替换为你的实际目标文件。
输出要求
每份文档都必须达到的交付标准——运行命令前请先了解这些要求。
层次清晰。 每份非简单文档都应有标题 → 一级标题 → 二级标题 → 正文,而不是一整页未设置样式的 Normal 段落。如果 view outline 显示的是一串扁平列表,就说明缺少层次结构。
明确设置标题字号(Word 默认样式的字号会因模板而异):H1 ≥ 18pt(长篇报告使用 20pt),H2 = 14pt 加粗,H3 = 12pt 加粗,正文 = 11–12pt,行距为 1.15–1.5 倍。优先使用 style=Heading1,而非行内字号设置,这样更换主题时只需修改一次样式定义;但如果无法信任模板样式,就要明确设置字号。
一种正文字体,一种强调色。 选用一种易读的正文字体(Calibri、Cambria、Georgia、Times New Roman);强调色用于突出标题或表头,不要使用彩虹色格式。
通过属性设置间距。 使用段落的 spaceBefore / spaceAfter。连续的空段落会破坏分页,并被 view issues 标记。
排版质量。 新增内容使用弯引号(‘ ’ “ ”),不要使用 ASCII 引号;可直接输入 Unicode 字符,也可在 raw-set 中使用 XML 实体(‘/’/“/”)。表示范围时使用短横线 –(2024–2026),用于插入说明时使用长破折号 —。
任何超过 1 页的文档都要有页眉、页脚和页码。 页码应通过实时 PAGE 字段(--prop field=page)插入,绝不能直接输入文本“Page 1”——CLI 会为你插入 <w:fldChar>(参见“页眉和页脚”)。
保留现有模板。 编辑已有样式的文件时,应与其风格保持一致;现有惯例优先于本指南。
视觉交付底线(适用于每份文档)
宣布完成前,运行 officecli view "$FILE" html 并读取返回的 HTML 路径,确认以下各项均符合要求:
- 不得将占位符标记渲染为实际内容。
$xxx$、{var}、{{name}}、<TODO>、lorem、xxxx绝不能出现在标题、正文、封面、目录、题注、页眉或页脚中。供用户填写的字面量{name}应放在醒目的说明段落中(例如“发送前请替换{name}”),不能作为最终内容直接呈现。 - 标题不得截断,单元格不得溢出。 加宽列,或设置
wrapText,不要删减内容。 - 文档有 3 个或更多标题时,必须包含目录(
--type toc)。 - 封面填充率至少为 60%,末页填充率至少为 40%。 封面内容过少时,可补充副标题、作者、日期、范围或重点概述;末页只有“Thank you”时,可补充结论、后续步骤、联系方式或法律信息。
- 文档文本中不得出现字面量
\$、\t、\n。 如果view text显示这些内容,说明 Shell 转义层泄漏了——请删除该段落并重新输入。
若有任何一项不符合要求,请先停止并修正,然后再宣布完成。
常见工作流
共六个步骤。每项非简单构建工作都应遵循以下流程。
- 打开文件。 使用
officecli open "$FILE"(默认驻留模式)。创建新文件时,先运行officecli create "$FILE"。 - 了解文件情况。 对于已有文件,运行
officecli view "$FILE" outline,查看标题树、章节数,以及是否已有目录/水印/修订。切勿在不了解文件情况时直接编辑。 - 逐步构建。 先处理结构,再添加内容,最后设置格式:样式和编号定义 → 分节/页面设置 → 标题和正文 → 表格/图片/字段/目录 → 页眉/页脚 → 批注。每次结构操作后,都要先用
get取回结果,再继续添加内容。 - 按规格设置格式。 明确设置标题字号、间距、宽度、对齐方式、制表位和列表缩进——格式是交付成果的一部分,不是可有可无的润色。
- 先保存,再以结构为准,而非依赖缓存文本。
officecli save "$FILE"会写入 XML。目录/PAGE/NUMPAGES/SEQ/PAGEREF 字段含有缓存值,在人手动重新计算前(在 Word 中按 F9),这些值可能过期或为空。请确认字段确实存在(get --depth 3能找到<w:fldChar>),不要只相信可见文本。 - QA——假定存在问题。 只有在一轮修复并验证后确认没有新问题,才算完成;不是最后一条命令退出代码为 0 就算完成。参见 QA。
快速开始
最精简可用的 docx:一个标题、一个正文段落、一个副标题,以及带有实时页码字段的页脚。请根据需要调整,不要直接复制粘贴——文件由你创建,内容由你编写。
FILE="review.docx"
officecli create "$FILE"
officecli open "$FILE"
officecli add "$FILE" /body --type paragraph --prop text="Q4 2026 Review" --prop style=Heading1 --prop size=20pt --prop bold=true --prop spaceAfter=12pt
officecli add "$FILE" /body --type paragraph --prop text="Revenue grew 18% year-over-year, ahead of plan." --prop size=11pt --prop spaceAfter=8pt
officecli add "$FILE" /body --type paragraph --prop text="Key Drivers" --prop style=Heading2 --prop size=14pt --prop bold=true --prop spaceBefore=12pt --prop spaceAfter=6pt
officecli add "$FILE" /body --type paragraph --prop text="Enterprise renewals, upsell, and a new EMEA region." --prop size=11pt
officecli add "$FILE" / --type footer --prop type=default --prop size=9pt --prop text="Page " --prop field=page
officecli set "$FILE" "/footer[1]/p[1]" --prop align=center
officecli save "$FILE"
officecli validate "$FILE"
已验证:validate 返回 no errors found;get /footer[1] --depth 3 显示包含 5 个 run 的 PAGE 字段链(begin / instrText / separate / cached value / end)。
阅读与分析
先纵览,再深入。outline 会告诉你文档已有的内容;确定查看位置后,再使用 view text / get / query。
officecli view "$FILE" outline # heading tree, section count, table/image counts, watermark, tracked-changes presence — orient here first
officecli view "$FILE" html # Read the returned HTML path: first visual check after a batch of edits (hierarchy, empty-para spacing, missing TOC)
officecli view "$FILE" text --start 1 --end 80 # text for content QA; paths shown as [/body/p[N]] so you can jump back with get
officecli view "$FILE" annotated # values + style/font/size + warnings per run
officecli view "$FILE" stats # paragraph counts, font usage, style distribution
officecli view "$FILE" issues # empty paras, missing alt text, spacing anomalies
officecli watch "$FILE" 会持续运行实时预览,供用户按需打开;Agent 自检使用 view html。最终视觉验证由用户在 Word / WPS / Pages 中打开 .docx 完成。
检查单个元素。 类 XPath 语义路径(从 1 开始计数)。始终加引号——shell 会对 [N] 执行 glob 匹配。使用 [last()](带括号)表示最后一个元素;[last] 会报错。添加 --json 可输出机器可读结果。
officecli get "$FILE" / # document root: metadata, page setup
officecli get "$FILE" "/body/p[1]" # one paragraph
officecli get "$FILE" "/body/p[1]/r[1]" # one run (character-level formatting)
officecli get "$FILE" "/body/tbl[1]" --depth 3 # table with rows and cells
officecli get "$FILE" "/footer[1]" --depth 3 # footer — check for fldChar
officecli get "$FILE" "/styles/Heading1" # style definition
officecli get "$FILE" /numbering --depth 2 # numbering abstractNum + num bindings
查询整个文档。 类 CSS 选择器,适用于系统化检查,而非逐项手动查看。运算符:=、!=、~=(包含)、>=、<=、[attr](存在)。完整参考:officecli query --help。
officecli query "$FILE" 'paragraph[style=Heading1]' # all H1s
officecli query "$FILE" 'p:contains("quarterly")' # text match
officecli query "$FILE" 'p:empty' # empty paragraphs (clutter)
officecli query "$FILE" 'image:no-alt' # accessibility gaps
officecli query "$FILE" 'paragraph[size>=24pt]' # numeric comparison
officecli query "$FILE" 'field[fieldType!=page]' # fields other than PAGE
query --json 会将结果封装在 .data.results[] 中——使用 jq '.data.results | length' 计数。
大型文档。 使用 view outline 按标题导航,并通过 query 跳转;不要将整个正文都导入上下文。
创建与编辑
动词:add(新建元素)、set(更改属性)、remove、move、swap、batch、raw-set(最后手段,直接操作 XML)。文档构建中 90% 的内容是段落、run、表格、少量图片、目录和页脚。
段落、run 和样式
段落(p)是一个块;run(r)是其中字符格式一致的一段文字。在 p 上设置段落级属性(样式、对齐方式、间距、缩进);在 r 上设置字体 / 大小 / 颜色 / 粗体。
officecli add "$FILE" /body --type paragraph --prop text="Executive Summary" --prop style=Heading1 --prop size=18pt --prop bold=true --prop spaceAfter=12pt
officecli set "$FILE" "/body/p[1]/r[1]" --prop color=1F4E79
使用 spaceBefore / spaceAfter 设置垂直间距——不要连续插入空段落。左缩进使用 --prop indent=720(twips),首行缩进使用 firstLineIndent=360,悬挂缩进使用 hangingIndent=720;行首空格会触发 view issues。
表格
表格路径为 /body/tbl[N],包含行 tr[N] 和单元格 tc[N]。添加表格时指定行数 / 列数,然后填充内容。
officecli add "$FILE" /body --type table --prop rows=4 --prop cols=3 --prop width=100%
officecli set "$FILE" "/body/tbl[1]/tr[1]" --prop header=true --prop c1=Quarter --prop c2="Revenue" --prop c3="Growth"
officecli set "$FILE" "/body/tbl[1]/tr[1]/tc[1]/p[1]/r[1]" --prop bold=true
行级 set 支持 height、header 和 c1 / c2 / … / cN 文本快捷方式(cN 可泛化为任意列数)。单元格格式(粗体、填充、颜色)应设置在单元格的段落 / run 上,而不是行级属性。若要设置单元格边框,请在 tc 上设置单元格级 border.*(--prop border.bottom="single;6;000000;0"),或在内部段落上设置段落级 pbdr.*。
水平线 = 段落底部边框,绝不能用单行表格。 用表格充当分隔线会渲染成带最小高度的空框(在页眉 / 页脚中尤其明显)。应在段落上使用 pbdr.bottom(STYLE;SIZE;COLOR):
officecli set "$FILE" "/body/p[3]" --prop pbdr.bottom="single;6;2E75B6"
列表(项目符号、编号、多级列表)
对于单级项目符号 / 编号列表,在段落上设置 listStyle(listStyle 是段落属性,不是 run 属性——这是常见错误):
officecli add "$FILE" /body --type paragraph --prop text="First item" --prop listStyle=bullet
对于多级列表(法律文书样式的 1 / 1.1 / 1.1.1),先添加 abstractNum,再添加 num,然后在每个段落中引用 numId:
officecli add "$FILE" /numbering --type abstractnum --prop format=decimal # → abstractNum id=0
officecli add "$FILE" /numbering --type num --prop abstractNumId=0 # → num id=1
officecli add "$FILE" /body --type paragraph --prop text="Section one" --prop numId=1 --prop ilvl=0
ID 从 0 开始:第一个 abstractNum 的 id=0;num 通过 abstractNumId=0 引用它,而 num 自身分配的 id=1。若 abstractNumId 不存在,则会报错,因此创建后请检查 ID。使用 officecli query "$FILE" 'paragraph[numId>0]' 验证。级别和格式选项请参阅 help docx abstractnum / help docx num。
制表位(签名行、前导符行)
制表位是段落的一级 tab 子元素;pos 接受 6in/6cm/twips,val ∈ left/center/right,leader ∈ none/dot/hyphen/underscore。参见 help docx tab。
officecli add "$FILE" "/body/p[1]" --type tab --prop pos=6in --prop val=right --prop leader=dot
前导符注意事项。 仅设置 leader=dot 不会显示点线——只有当文本与制表位之间的某个 run 中有实际的 <w:tab/> 字符时,前导符才会呈现。可在文本中使用 \t 插入:先定义制表位(add tab --prop pos=6in --prop val=right --prop leader=dot),再设置 --prop text="Chapter 1\t12"——\t 会变成 <w:tab/>,点线会延伸至右对齐的页码。(也可以直接使用 text="Chapter 1 ......... 12",但实际的制表位能实现整齐对齐。)
域(PAGE / NUMPAGES / DATE / MERGEFIELD / REF)
域是在渲染时计算的动态值。fieldType 用于选择域;name 用于指定目标(合并名称或 ref 书签);format / instr 用于添加开关。
| 域 | 用途 | 示例 |
|---|---|---|
page | 当前页码 | 在页脚中使用 --prop field=page,或在行内使用 --prop fieldType=page |
numpages | 总页数 | --prop field=numpages / --prop fieldType=numpages |
date | 今天的日期 | --prop fieldType=date --prop format='yyyy-MM-dd' |
mergefield | 模板合并标记 | --prop fieldType=mergefield --prop name=CustomerName |
ref | 对书签的交叉引用 | --prop fieldType=ref --prop name=bookmarkName |
完整的 fieldType 枚举(包含 pageref、seq、styleref、docproperty、createdate 等 30 多个值)请参见 help docx field。不存在 fieldInstr 这一 fieldType——当类型化快捷方式无法满足需求时,请使用 instruction 属性传入原始域指令文本。图片开关(MERGEFIELD Amount \# "#,##0.00"、DATE \@ "yyyy年MM月")通过 --prop instruction='…' 设置(mergefield 的 format 属性会被忽略并显示警告——请使用 instruction)。
officecli add "$FILE" "/body/p[3]" --type field --prop fieldType=mergefield --prop name=customer_name
# Renders «customer_name» — visible placeholder, replaced in Word at mail-merge time.
MERGEFIELD 模板:不要渲染占位符文本。 将 {{customer_name}} 或 $NAME$ 作为正文文本显示,是失败的模板,收件人会看到这些内容——请插入真实的 MERGEFIELD(见上文),或将字面标记限制在明显的说明段落中。使用 query 'field[fieldType=mergefield]' 确认。
SEQ / PAGEREF / TOC 域值。 officecli 在写入时不会存储已渲染的域值。请根据各路径的需求重新计算:
- SEQ 编号(
Figure 1/2/3):officecli set "$FILE" / --prop recalcFields=seq会按正文文档顺序统计 SEQ 域并写入缓存值(evaluated会变为 true;开关和格式请参见help docx document)。相对于标题的\s和页眉/页脚中的 SEQ 会交由 Word 处理。 - PAGE / PAGEREF / NUMPAGES / TOC 页码需要分页,而 officecli 没有分页引擎——
officecli set "$FILE" /settings --prop updateFields=true会将其交由 Word 在打开文件时处理。
多图表文档请同时使用两者。学术论文:参见 officecli-academic-paper 技能。
页眉和页脚(页码)
单命令模式——CLI 会插入 <w:fldChar>,因此无需手动编写域:
# Empty first-page footer — auto-enables differentFirstPage so the cover has no page number
officecli add "$FILE" / --type footer --prop type=first --prop text=""
# Default footer with live page number
officecli add "$FILE" / --type footer --prop type=default --prop align=center --prop size=9pt --prop text="Page " --prop field=page
如果页眉和页脚都存在,默认页脚为 /footer[2];如果只有页脚,则为 /footer[1]。验证:get --depth 3 必须显示 fldChar 子元素,而不能只是包含字面文本 "Page" 的 run(view outline 对动态域和静态文本都会打印“Footer: Page”,不要依赖它)。不要执行 set --prop differentFirstPage=true——该属性不受支持(退出码为 2,并显示 WARNING: UNSUPPORTED;但元素仍会创建——请检查 --json 中的 success);添加 first 类型的页脚会切换该标志。对于组合页码 Page X of Y,请参见配方 (b)。
目录
对于包含 3 个或更多标题的文档,先确认请求范围内确实存在有效来源。目录来源必须使用内置标题样式,或带有 outlineLvl 的自定义段落样式;加粗或字号较大的普通文本不算来源。如果没有符合条件的来源,请先修正标题结构,而不是插入一个会显示“Error! No table of contents entries found.”的目录。
# Built-in Heading styles are TOC sources.
officecli add "$FILE" /body --type paragraph --prop text="Introduction" --prop style=Heading1
# Custom paragraph styles need an outline level (0 = Heading 1).
officecli add "$FILE" /styles --type style --prop id=ThesisH1 --prop type=paragraph --prop outlineLvl=0
# Add the TOC only after its sources exist.
officecli add "$FILE" /body --type toc --prop levels="1-3" --prop title="Table of Contents" --prop hyperlinks=true --index 0
页码需要分页才能确定;OfficeCLI 无法自行计算目录页码。设置 updateFields=true,让 Word 在打开文档时重新计算目录(以及所有域)。如果没有兼容 Word 的域引擎,请说明目录是动态且尚未计算的;不要声称页码已就绪,也不要猜测静态目录。
officecli set "$FILE" /settings --prop updateFields=true
使用 /toc[1] 或 /tableofcontents,通过 get/set/remove 直接操作目录。
图片
图片必须放在运行中。为确保无障碍访问,必须提供替代文本——创建时直接传入 alt:
officecli add "$FILE" "/body/p[5]" --type picture --prop src=logo.png --prop width=1.5in --prop alt="Acme logo"
交付前,确认 officecli query "$FILE" 'image:no-alt' 的结果为空。
图表
对于数据,添加原生图表——可编辑、可应用主题、支持无障碍访问,并能在 Word 中重新渲染;切勿使用扁平化的图表 PNG 截图。每个系列使用 data="Label:v1,v2,…";每个系列设置一个 data=(或使用 series1=/series2=)。
officecli add "$FILE" /body --type chart --prop chartType=bar --prop title="Revenue by Region" --prop categories="EMEA,APAC,Americas" --prop data="2026:120,150,180"
chartType ∈ bar / column / line / pie / area / scatter(使用 help docx chart 查看坐标轴/图例/系列样式设置)。对于 officecli 无法创建的特殊图表,PNG 配合 --type picture 只能作为后备方案。
超链接和书签
外部链接通过 hyperlink 添加:
officecli add "$FILE" "/body/p[2]" --type hyperlink --prop url="https://example.com" --prop text="our site"
内部链接(指向书签)使用 --prop anchor=bookmarkName——不要在 url 中使用 #fragment:
officecli add "$FILE" "/body/p[2]" --type hyperlink --prop anchor=chapter1 --prop text="See Chapter 1"
另一种方式是将 PAGEREF 域与可见文本配对。请参阅 help docx hyperlink / help docx bookmark。
分节和页面设置
文档根节点 / 携带页面设置(pageWidth、pageHeight、页边距,单位为 twip)。多分节文档(横向页面、分栏)需添加 section 分节符——请参阅 help docx section。camelCase(pageWidth,规范形式)和小写别名(pagewidth)均可使用;建议使用 camelCase。
officecli set "$FILE" / --prop pageWidth=12240 --prop pageHeight=15840 --prop marginTop=1440 --prop marginLeft=1440
# Newspaper-style multi-column flow (columnSpace in twips; 720 = 0.5in):
officecli set "$FILE" / --prop columns=2 --prop columnSpace=720
强制分页
每个逻辑边界只能使用一种分页机制。默认做法是在目标标题上设置 pageBreakBefore=true。也可以在标题前插入一个显式的 pagebreak。同一边界绝不要同时使用这两种机制:双重分页可能导致出现空白页。添加 pagebreak 后,绝不要在紧接其后的 p[last()] 上设置 pageBreakBefore。
# Default: apply the break directly to the heading.
officecli add "$FILE" /body --type paragraph --prop text="Introduction" --prop style=Heading1 --prop pageBreakBefore=true
--prop break=newPage 是 pageBreakBefore=true 的别名。使用 view html 预览并检查是否有空白页。
报告级配方
每份长篇报告中都会用到的模式。每种模式都已执行并通过 validate 验证。
(a) 丰富的封面 — 达到 ≥ 60% 的填充率下限。 依次添加保密横幅、标题、副标题、客户/项目/日期信息块和关键主题栏,然后强制下一节从新页面开始:
officecli add "$FILE" /body --type paragraph --prop text="CONFIDENTIAL — CLIENT USE ONLY" --prop align=center --prop size=9pt --prop color=C00000 --prop spaceAfter=24pt
officecli add "$FILE" /body --type paragraph --prop text="Strategic Growth Review" --prop style=Title --prop size=32pt --prop bold=true --prop align=center --prop font=Cambria --prop spaceAfter=8pt
officecli add "$FILE" /body --type paragraph --prop text="FY26 Outlook and Scenario Planning" --prop italic=true --prop size=16pt --prop align=center --prop spaceAfter=36pt
officecli add "$FILE" /body --type paragraph --prop text='Prepared for: Acme Corp. Leadership Team' --prop align=center --prop size=11pt
officecli add "$FILE" /body --type paragraph --prop text='Engagement: 2026-04 — 2026-06' --prop align=center --prop size=11pt --prop spaceAfter=36pt
officecli add "$FILE" /body --type paragraph --prop text="Key themes: 1) margin resilience, 2) EMEA expansion, 3) capital allocation." --prop align=center --prop italic=true --prop size=10pt
officecli add "$FILE" /body --type paragraph --prop text="Executive Summary" --prop style=Heading1 --prop pageBreakBefore=true
(b) 第 X 页,共 Y 页页脚 — 组合使用 PAGE + NUMPAGES。 添加页脚段落,然后通过三个子操作动态生成 Page <X> of <Y>。这是官方的 help docx footer 配方。
officecli add "$FILE" / --type footer --prop type=default --prop text="Page " --prop align=center --prop size=9pt
officecli add "$FILE" "/footer[1]/p[1]" --type field --prop fieldType=page
officecli add "$FILE" "/footer[1]/p[1]" --type run --prop text=" of "
officecli add "$FILE" "/footer[1]/p[1]" --type field --prop fieldType=numpages
officecli get "$FILE" "/footer[1]/p[1]" --depth 1 | grep -o fldChar | wc -l # expect ≥ 4; use grep -o ... | wc -l, NOT grep -c (single-line XML returns 1)
(c) 带底纹和白色粗体文字的表头行。 顺序很重要——先填充表头单元格文本(空单元格中不存在 runs;在空单元格上执行 set …/tc[N]/p[1]/r[1] 会报错 "No r found"),再设置单元格底纹,最后设置 run 格式:
officecli add "$FILE" /body --type table --prop rows=5 --prop cols=4 --prop width=100%
officecli set "$FILE" "/body/tbl[1]/tr[1]" --prop header=true --prop c1=Quarter --prop c2=Revenue --prop c3=Growth --prop c4=Status
for col in 1 2 3 4; do
officecli set "$FILE" "/body/tbl[1]/tr[1]/tc[$col]" --prop fill=1F4E79
officecli set "$FILE" "/body/tbl[1]/tr[1]/tc[$col]/p[1]/r[1]" --prop bold=true --prop color=FFFFFF
done
for row in 3 5; do for col in 1 2 3 4; do
officecli set "$FILE" "/body/tbl[1]/tr[$row]/tc[$col]" --prop fill=D9E2F3 # zebra stripe
done; done
(d) 财务表格 — 数字右对齐、总计加粗、总计行添加底部边框。
for row in 2 3 4 5; do for col in 2 3 4; do
officecli set "$FILE" "/body/tbl[1]/tr[$row]/tc[$col]/p[1]" --prop align=right
done; done
for col in 1 2 3 4; do
officecli set "$FILE" "/body/tbl[1]/tr[5]/tc[$col]/p[1]/r[1]" --prop bold=true
officecli set "$FILE" "/body/tbl[1]/tr[4]/tc[$col]/p[1]" --prop pbdr.bottom="single;6;000000;0"
done
(e) 包含多个项目符号的单元格(SWOT / 风险矩阵)。 c1="a\nb" 会在一个段落中生成 <w:br/> 换行符——适用于纯文本多行内容,但项目符号需要使用独立段落。先通过 set c1= 创建第一项,然后在单元格下为后续每项执行 add paragraph(设置 listStyle=bullet):
officecli set "$FILE" "/body/tbl[1]/tr[1]" --prop c1="Installed base of 18k enterprise seats"
officecli add "$FILE" "/body/tbl[1]/tr[1]/tc[1]" --type paragraph --prop text="Margin structure above peer median" --prop listStyle=bullet
officecli set "$FILE" "/body/tbl[1]/tr[1]/tc[1]/p[1]" --prop listStyle=bullet
如果初始行出现在底部,请重新排序:officecli move "$FILE" "/body/tbl[1]/tr[1]/tc[1]/p[N]" --index 0。
(f) 不使用字段引擎的目录。 仅使用 CLI 的工作流无法计算可靠的页码。保留动态目录,设置 updateFields=true,并告知接收者在 Word 或其他兼容的字段引擎中打开文档。不要用猜测的静态页码替换它。
模板交付 — 将模板备注与面向最终用户的内容分开
HR / 法律 / 供应商模板中包含仅供内部使用的指导("replace {{CompanyName}}"),这些内容绝不能随模板一起交付。以下两种模式均可行:
- 在明确的
Heading 1("HR 用户的模板备注")下添加末尾的“模板备注”章节,并将所有说明放在该章节中;分发前,从该标题开始向下执行remove(使用query 'paragraph[style=Heading1]:contains("Template Notes")'定位)。 - 使用
__template_notes_start/_end书签标记内部章节的边界;交付时,raw-set会移除锚点之间的所有内容。
模板交付检查:移除内容后,query 'p:contains("Template Notes")' 和 query 'p:contains("{{")' 都应返回空结果。如果有备注段落残留,后续员工就会看到内部内容。
高级/专业主题(如果你在编写报告,可跳过)
报告、备忘录、信函、提案和 HR 模板不需要了解这些内容。只有当你的文档属于学术文档(包含公式、脚注、参考文献)、经过审阅(包含评论、修订记录)或带有标记(水印)时,才继续阅读。
公式和脚注。 --type equation 接受 LaTeX——\frac、\sum、希腊字母、\mathit、\mathcal 均可正常渲染。默认情况下,它会创建独立的 /body/oMathPara[N] 显示块;若要在正文中插入行内 <m:oMath>,请使用段落父路径,并传入 --prop mode=inline(add "/body/p[N]" --type equation --prop formula=… --prop mode=inline)。脚注会按段落索引自动编号。参考文献悬挂缩进:每条条目设置 firstLineIndent=-720 indent=720。
officecli add "$FILE" /body --type equation --prop formula="\\frac{a}{b} + \\sum_{i=1}^{n} x_i"
officecli add "$FILE" "/body/p[3]" --type footnote --prop text="See Appendix A for methodology."
评论和修订记录。 批量接受/拒绝:set "$FILE" /revision --prop revision.action=accept(或 --prop revision.action=reject);也可以使用 /revision[@author=Alice] 或 /revision[@type=ins] 之类的选择器进行筛选。使用 query ins 和 query del 定位单条修订(trackedchange 不是选择器)。使用 --prop revision.type=ins|del --prop revision.author=… 在文本片段上创建修订记录(完整的 revision.* 选项集——包括 format/moveFrom/moveTo——请参阅 help docx run)。添加评论:add "/body/p[4]" --type comment --prop author=… --prop text=…;使用 --prop parentId=N 添加回复,并使用 set "/comments/comment[N]" --prop done=true 将其标记为已解决(将评论标记为已解决而非删除,以保留审计记录——随后运行 query 'comment[done=false]' 可列出仍未解决的评论)。属性模式:help docx comment/help docx run。
水印。 一条命令即可完成:add / --type watermark --prop text="DRAFT" --prop color=BFBFBF --prop opacity=0.8(默认不透明度为 0.5);之后可通过 set /watermark --prop opacity=… 调整。
何时切换技能。 章节草稿、≤ 3 个脚注、≤ 2 个公式,且不含参考文献/交叉引用时,继续使用 docx。需要引用格式(APA/Chicago/IEEE/GB 7714)、正文↔参考文献自动链接、带 \ref 的编号公式、“List of Figures” 或自动更新交叉引用时,切换到 academic-paper。当文档用于数据采集时(可填写表单、带用户填写区域的合同、问卷、邮件合并模板(<w:sdt> 内容控件、<w:ffData>、documentProtection=forms)),切换到 officecli-word-form。
原始设置应急方案(L1/L2/L3)
精度分为三个级别;选择能满足需求的最低级别。
- L1 — 高级属性(
--prop text=…、--prop style=Heading1):默认选项,适用于 80% 的情况。 - L2 — 点分属性回退方案(
pbdr.top=、ind.left=、shd.fill=、padding.top=、font.size=):当 L1 缺少所需选项时使用。示例:--prop pbdr.bottom="single;6;1F4E79;0"。生成符合模式的 XML。 - L3 — 使用 XML 的
raw-set:最后手段,不提供模式保护。用于内部超链接、复合字段,以及类型化动词无法表达的其他结构(参见 XML 附录)。
边框格式为 style;size;color;space:single;4;FF0000;1。十六进制颜色前面不能带 #:FF0000。方案颜色名称(accent1..6、dark1/dark2、light1/light2、hyperlink)可在任何允许使用十六进制颜色的位置使用;为确保颜色在不同主题间保持一致,建议优先使用十六进制颜色。
QA(必需)
假设文档存在问题——QA 是一场 Bug 搜寻,而不是确认步骤。 你的第一份文档几乎从来都不正确;如果初次检查就没有发现任何问题,说明你检查得还不够仔细。标题看起来没问题,直到 view outline 显示 H3 直接位于 H1 下方;页脚显示“第 1 页”,直到 get --depth 3 显示它是静态文本片段,而不是字段。
在标记“完成”前进行的最少检查周期
officecli view "$FILE" issues— 检查空段落、缺失的替代文本和格式异常。officecli view "$FILE" outline— 检查标题层级(不得跳过 H1 → H3)、是否存在目录以及章节数量。officecli view "$FILE" text --max-lines 400— 检查拼写错误、多余的\$/\t/\n字面量和占位符。officecli validate "$FILE"— 检查架构(交付门会在已关闭并写入磁盘的文件上重新运行此检查)。- 视觉检查——将整份文档作为联系表查看(仅限具备视觉能力的 Agent——如果你无法解读图像,请跳过此步骤:步骤 1–4 就是你的能力上限,并在交接时将文档标记为“未经视觉验证”)。运行
officecli view "$FILE" screenshot --grid auto -o /tmp/sheet.png,然后读取图像。--grid auto会将所有页面平铺到一张图像中(自动选择列数;使用--grid 4强制指定)——你可以看到分页、空白页、标题节奏、页边距是否失衡,以及目录和封面的摆放位置,而不仅仅是 DOM。Windows + Word 会通过真实的 Word 渲染每一页;其他环境则使用 HTML。如果截图失败,请改用view html,并将跨页断裂、对齐和节奏标记为“未经视觉验证”。缩略图只能用来定位:对任何细节问题(列对齐、行距、缩进、深色背景上的深色文字、题注位置),都要在可疑页面上使用screenshot --page N以全分辨率确认(不加--grid;Windows 上使用真实的 Word)。通过“validate”不等于可以交付;“看起来像一份真正的文档”才算。 - 如果有任何项目未通过,请修复,然后重新运行完整周期——一次修复通常会引发另一个问题。
交付门(交接前运行——任何一项失败都将导致拒收,请勿交付)
复制粘贴并设置 FILE;在每项检查都打印 OK 之前,不要声明完成。
FILE="your-file.docx"
# Gate 1 — schema.
officecli close "$FILE" 2>/dev/null
officecli validate "$FILE" | grep -q "no errors found" || { echo "REJECT Gate 1: validate failed"; exit 1; }
echo "Gate 1 OK"
# Gate 2 — token leak (shell-escape / template tokens / literal \$ \t \n). grep -c never false-PASSes.
LEAK=$(officecli view "$FILE" text | grep -cE '(\$[A-Za-z_]+\$|\{\{[^}]+\}\}|<TODO>|xxxx|lorem|\\[\$tn])')
[ "$LEAK" -eq 0 ] && echo "Gate 2 OK" || { echo "REJECT Gate 2: $LEAK leak line(s)"; officecli view "$FILE" text | grep -nE '(\$[A-Za-z_]+\$|\{\{[^}]+\}\}|<TODO>|xxxx|lorem|\\[\$tn])'; exit 1; }
# A TOC placeholder is valid before a Word-compatible field engine updates it; confirm the TOC field and updateFields setting structurally instead.
# Gate 3 — live PAGE field exists when a footer is expected.
FLD=$(officecli query "$FILE" 'field[fieldType=page]' --json | jq '.data.results | length')
[ "$FLD" -ge 1 ] && echo "Gate 3 OK" || { echo "REJECT Gate 3: no live PAGE field"; exit 1; }
echo "Delivery Gate PASS"
字段/缓存值抽查
字段写入时携带的缓存值可能已过时或为空——请通过结构而非文本确认字段是否存在。
- 页脚 PAGE:
get /footer[N] --depth 3会列出 begin / instrText / separate / cached / end 运行链——单个 PAGE 字段至少需要 5 个运行,组合字段“Page X of Y”至少需要 11 个运行。单个文本为"Page"的运行表示字段缺失;请使用--prop field=page重新添加。 - 目录:
get /toc[1] --depth 2会显示字段结构。重新计算前,页码可能显示为1 1 1 1或Update field to see…(参见 §Table of Contents — setupdateFields=true)。 - MERGEFIELD:
query 'field[fieldType=mergefield]'— 每个插槽应有一个字段,其他位置不得出现字面量{{name}}。
能力边界
validate 能捕获架构错误,但不能发现设计错误——文档即使标题层级错误、使用伪造的 Heading 1 字号、正文包含占位符,或无封面文档的首页页脚为空,也可能通过检查。联系表视觉检查(screenshot --grid)和字段结构检查,才能发现验证无法捕获的问题。
QA 显示说明(无需处理)
- 无论渲染后的编号是什么,
view text对每个编号列表项都显示"1."——实际输出会正确递增。 view issues会在封面段落、居中标题、列表项和参考文献条目上报告“正文段落缺少首行缩进”——首行缩进仅适用于 APA/学术正文;对于块状排版的专业文档,这些提示属于预期情况。
已知问题与陷阱
遇到某些内容“看起来有问题”时,请先判断原因再着手处理:[AGENT-ERROR] 文档有误(应修复)· [RENDERER-BUG] 文档正确,但查看器的渲染方式不同(无需追查)· [SKILL gap] 技能说明未涵盖此规则(请提交问题)。
渲染器问题(跨查看器,[RENDERER-BUG] — 无需追查)
在判定颜色/字段/图表损坏之前,先在用户指定的查看器中打开文件;如果在那里显示正常,那就是查看器问题。
- PAGE 字段可能会直接显示字面文本“Page”(没有数字),直到重新计算——应根据是否存在
fldChar来判断,而不是看数字。 - 目录缓存的页码可能显示为“1 1 1 1”,直到按下 F9。
- 饼图/圆环图的填充可能会塌缩为一种颜色,在某些查看器中如此(柱形图/条形图显示正常)。
- 表单控件复选框可能显示为双框;OMML 公式的基线可能因查看器而异(XML 相同)。
常见陷阱
| 陷阱 | 正确做法 |
|---|---|
--index 与 [N] | --index 从 0 开始;[N] 路径从 1 开始 |
多次使用相同的 N 执行 add --index N | 每次插入都会将后续内容下移;重复使用 N 会使后插入的项目位于先插入的项目之前——按相反顺序插入,或使用以 paraId 为锚点的 move --after/--before |
在 zsh/bash 中不加引号的 [N] | 所有路径都加引号:"/body/p[1]" |
将 [last] 用作谓词 | 必须写成 [last()],带括号 |
| 间距中使用原始 twips | 使用带单位的值:12pt、0.5cm、1.5x |
| 使用空段落调整间距 | 使用 spaceBefore / spaceAfter |
使用行级 set 设置单元格格式 | 行级 set 仅支持 height、header、c1..cN 文本;格式应设置在单元格段落/文本运行上 |
在文本运行上设置 listStyle | 这是段落属性 |
| 通过前导空格缩进 | 使用 indent=720 / firstLineIndent=360 / hangingIndent=720(带点号的 ind.left / ind.firstLine 也可以) |
通过 set differentFirstPage=true 隐藏封面页码 | 不支持——添加首页类型的页脚:--type footer --prop type=first --prop text="" |
| 需要新章节从新页开始 | 在标题上使用 pageBreakBefore=true;也可改用显式 pagebreak,但两者不可同时使用 |
| 一个单元格中有多个项目符号段落 | c1="a\nb" 会生成 <w:br/> 换行符(仍是一个段落);如需分开的项目符号段落,请使用方案 (e) |
dotted-attr 可用时使用 raw-set | 优先使用 L2 dotted-attr,而不是 L3 raw-set |
| 下一段继承前一段的 Heading 样式 | 在后续段落上明确设置 --prop style=Normal |
| 修改在 Word 中打开的文件 | 先在 Word 中关闭文件 |
输出到批处理的 Echo 遇到 $/' 会出错 | 使用单引号分隔符的 heredoc:cat <<'EOF' | officecli batch … |
Raw-set XML 附录(L3 模式)
raw-set 注入字面 OOXML — 不受架构保护。<w:pPr> 中元素的顺序:pStyle、numPr、spacing、ind、jc、rPr(最后)。智能引号使用实体(‘/’/“/”)。任何包含前置或尾随空格的 <w:t> 都要添加 xml:space="preserve"。RSID 为 8 位十六进制数。除非用户指定其他作者,否则跟踪更改/评论的作者使用 “Claude”。
跟踪更改中的插入/删除 — 优先对 run 使用高级 --prop revision.type=ins|del;只有在类型化路径无法实现时才使用 raw-set(例如下文中拒绝/还原其他作者的更改)。替换整个 <w:r>…</w:r>,绝不要在 run 内注入标签;将原始 <w:rPr> 复制到两处,以保留格式。在 <w:del> 内使用 <w:delText>(指令使用 <w:delInstrText>):
<w:r><w:t>The term is </w:t></w:r>
<w:del w:id="1" w:author="Claude" w:date="2026-01-01T00:00:00Z"><w:r><w:delText>30</w:delText></w:r></w:del>
<w:ins w:id="2" w:author="Claude" w:date="2026-01-01T00:00:00Z"><w:r><w:t>60</w:t></w:r></w:ins>
<w:r><w:t> days.</w:t></w:r>
删除段落/列表项的所有内容时,也要将段落标记为已删除(在 <w:pPr><w:rPr> 内添加 <w:del/>)— 否则接受更改后会留下空段落。要拒绝其他作者的插入,将你的 <w:del> 嵌套在对方的 <w:ins> 中;要还原对方的删除,在其后添加一个 <w:ins>(不要修改对方的内容)。
指向书签的内部超链接(优先使用高级 --prop anchor= 路径;仅在命令无法实现自定义 run 样式时使用 raw-set):
<w:hyperlink w:anchor="chapter1"><w:r><w:rPr><w:rStyle w:val="Hyperlink"/></w:rPr><w:t>See Chapter 1</w:t></w:r></w:hyperlink>
单个 run 中的复合域(例如,单命令路径无法组合的两个域)— fldChar begin / instrText / separate / value / end 链:
<w:r><w:fldChar w:fldCharType="begin"/></w:r>
<w:r><w:instrText xml:space="preserve"> PAGE </w:instrText></w:r>
<w:r><w:fldChar w:fldCharType="separate"/></w:r>
<w:r><w:t>1</w:t></w:r>
<w:r><w:fldChar w:fldCharType="end"/></w:r>
评论标记是 <w:r> 的同级元素,绝不能位于其内部(回复串联和已解决状态通过高级路径设置 — 使用 --prop parentId=/done=,参见上文“评论”):
<w:commentRangeStart w:id="0"/><w:r><w:t>annotated text</w:t></w:r><w:commentRangeEnd w:id="0"/>
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="0"/></w:r>
使用 officecli set "$FILE" /settings --prop updateFields=true 强制在打开时重新计算域(写入 <w:updateFields w:val="true"/>;适用于依赖布局的域 PAGE / PAGEREF / NUMPAGES / TOC 页码 — 无需使用 raw-set)。对于 SEQ 编号,优先使用 set / --prop recalcFields=seq,以便立即写入正确的缓存值,无需等待 Word。
帮助指引
不确定时:officecli help docx、officecli help docx <element>、officecli help docx <verb> <element>,Agent 可使用 --json。帮助内容是权威架构;本技能是决策指南。