docx 修订追踪(Track Changes)完整指南:用 InsertedTextRun、DeletedTextRun 与 revision 属性生成带修订标记的 Word 文档

发布时间:2026/9/17 9:29:21

docx 修订追踪(Track Changes)完整指南:用 InsertedTextRun、DeletedTextRun 与 revision 属性生成带修订标记的 Word 文档 docx 修订追踪Track Changes完整指南用 InsertedTextRun、DeletedTextRun 与 revision 属性生成带修订标记的 Word 文档【免费下载链接】docxEasily generate and modify .docx files with JS/TS with a nice declarative API. Works for Node and on the Browser.项目地址: https://gitcode.com/GitHub_Trending/do/docx本指南基于 docx 库Easily generate and modify .docx files with JS/TS支持 Node 与浏览器环境的修订追踪Change Tracking / Track Changes能力讲解如何在程序中直接生成带有插入、删除、格式变更、段落/节/表格属性变更、图片插入删除等修订标记的 .docx 文档。读完本文你将掌握InsertedTextRun、DeletedTextRun、TextRun.revision、Paragraph.revision、表格行/单元格的插入删除标记以及ImageRun修订等全部 API 用法并理解其在 OOXMLWordprocessingML层面的底层原理与源码实现。修订追踪的 OOXML 底层机制在 Word 的 WordprocessingML 文档中修订追踪主要由三类元素承载w:ins标记一段插入内容属性包含修订的w:id、w:author与w:datew:del标记一段删除内容同样携带上述修订元数据w:trackRevisions位于settings.xml中告诉 Word 在打开文档后自动追踪用户新做的修改。docx 库在源码中为这些元素建立了完整映射track-revision/track-revision.ts 定义了修订元数据类型IChangedAttributesPropertiesid、author、date三个必填字段以及负责输出w:id/w:author/w:date属性的ChangeAttributes组件insertion-track-change.ts 与 deletion-track-change.ts 分别将其包装为w:ins与w:del根元素。本文其余章节的所有 API最终都会落到这三个底层机制上。文本级修订InsertedTextRun 与 DeletedTextRun在Paragraph的children中除了普通的TextRun你还可以直接放入InsertedTextRun或DeletedTextRun从而把一段文本标记为“插入”或“删除”。import { Paragraph, TextRun, InsertedTextRun, DeletedTextRun } from docx; const paragraph new Paragraph({ children: [ new TextRun(This is a simple demo ), new TextRun({ text: on how to , }), new InsertedTextRun({ text: mark a text as an insertion , id: 0, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, }), new DeletedTextRun({ text: or a deletion., id: 1, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, }), ], });需要注意与普通TextRun可以直接传字符串不同如new TextRun(some text)InsertedTextRun与DeletedTextRun必须以配置对象的形式传入因为修订追踪所需的id、author、date字段必须被提供。除此之外它们与普通TextRun一样支持各种文本属性例如bold、color、size、font、shading、break等import { Paragraph, TextRun, InsertedTextRun, DeletedTextRun } from docx; const paragraph new Paragraph({ children: [ new TextRun(This is a simple demo), new DeletedTextRun({ text: with a deletion., color: ff0000, bold: true, size: 24, id: 0, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, }), ], });源码视角这些 Run 如何工作从源码看inserted-text-run.ts 中InsertedTextRun的选项类型是IChangedAttributesProperties IRunOptions即“修订元数据 普通 Run 格式选项”的组合。构造时它会以w:ins为根元素先压入ChangeAttributes输出w:id/w:author/w:date再在内部嵌套一个标准TextRun作为子元素w:ins w:id0 w:authorFirstname Lastname w:date2020-10-06T09:00:00Z w:r…格式与文本内容…/w:r /w:insdeleted-text-run.ts 中DeletedTextRun以w:del为根元素并额外通过内部DeletedTextRunWrapperw:r处理特殊内容包括普通文本包装为DeletedText、break换行以及对PageNumber.CURRENT、PageNumber.TOTAL_PAGES、PageNumber.TOTAL_PAGES_IN_SECTION等页码域代码的特殊处理——删除的页码字段会使用专用的DeletedPage/DeletedNumberOfPages/DeletedNumberOfPagesSection元素见 deleted-page-number.ts。这意味着你甚至可以在页眉页脚里删除/插入“第 X 页 / 共 Y 页”这类域代码demo/60-track-revisions.ts 中就展示了在页脚中删除 to 并插入 from 页码字段的完整示例。在页脚中使用修订 RunInsertedTextRun与DeletedTextRun不仅可以用在正文段落中也可以放进Footer里。下面的代码来自 demo/60-track-revisions.ts演示了在页脚中结合页码字段进行修订import { Footer, Paragraph, TextRun, PageNumber, DeletedTextRun, InsertedTextRun } from docx; new Footer({ children: [ new Paragraph({ alignment: AlignmentType.CENTER, children: [ new TextRun(Awesome LLC), new TextRun({ children: [Page Number: , PageNumber.CURRENT], }), new DeletedTextRun({ children: [ to , PageNumber.TOTAL_PAGES], id: 4, author: Firstname Lastname, date: 2020-10-06T09:05:00Z, }), new InsertedTextRun({ children: [ from , PageNumber.TOTAL_PAGES], bold: true, id: 5, author: Firstname Lastname, date: 2020-10-06T09:05:00Z, }), ], }), ], });同样地脚注footnotes内容中也支持修订 Run——demo/60-track-revisions.ts 在脚注段落里同时使用了DeletedTextRun与InsertedTextRun来演示“删除旧句、插入新内容”的修订效果。全局开启修订追踪features.trackRevisions除了手动用InsertedTextRun/DeletedTextRun标记内容还可以通过文档设置开启修订追踪开关让 Word 在用户之后编辑该文档时自动记录新的修改import { Document } from docx; const doc new Document({ features: { trackRevisions: true, }, });源码视角w:trackRevisions 元素从源码看features.trackRevisions会被传递到设置对象在 file.ts 中trackRevisions: options.features?.trackRevisions被注入Settings并在 settings/settings.ts 中输出为w:trackRevisions /元素。对应的单元测试位于 settings/settings.spec.ts断言w:settings数组包含{ w:trackRevisions: {} }与 file.spec.ts。需要特别理解的是trackRevisions: true的作用是“文件生成后Word 将自动追踪此后在文档上产生的新修改”它本身不会给既有内容添加任何w:ins/w:del标记。也就是说即便不设置该开关前面手动创建的插入/删除 Run 依然会正常显示为修订demo 源码的注释中也明确说明了这一点该开关解决的是“后续人工编辑是否被记录”的问题。格式变更修订TextRun 的 revision 属性如果想要表达“这段文本的样式发生过变更”例如从非粗体变成了粗体可以给TextRun添加一个revision属性。修订对象中需要包含变更前该 Run 的全部样式属性Word 据此判断新旧样式的差异new TextRun({ bold: true, text: This text is now bold and was previously not, revision: { id: 1, author: Firstname Lastname, date: 2020-10-06T09:05:00Z, bold: false, }, }).break();上面示例表达的是当前 Run 是粗体bold: true而修订记录revision.bold: false表明它“之前不是粗体”从而在 Word 中呈现为一次粗体格式修订。demo/60-track-revisions.ts 中也包含一个类似的revision示例id: 4bold: true当前、bold: false先前。这一机制在 OOXML 中对应w:rPrChangeRun 属性变更元素核心原则是“revision 内必须复述变更前的完整样式快照”。段落属性修订Paragraph 的 revision段落属性对齐方式、间距、缩进、边框、标题级别等的变更同样可以被追踪方法是直接在Paragraph配置上添加revision属性且该 revision 必须包含变更前的所有属性值import { Paragraph, AlignmentType, HeadingLevel } from docx; const paragraph new Paragraph({ text: This paragraph has changed alignment and heading, heading: HeadingLevel.HEADING_1, alignment: AlignmentType.RIGHT, spacing: { before: 400, }, revision: { id: 8, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, heading: HeadingLevel.HEADING_2, alignment: AlignmentType.LEFT, spacing: { before: 200, }, }, });上例中段落当前的属性是“标题 1 右对齐 段前 400”而revision内记录的是变更前的“标题 2 左对齐 段前 200”Word 会将其呈现为一次段落属性修订底层对应w:pPrChange元素。对于这类“当前值 先前值”成对出现的修订务必确保两者结构一致、字段完整否则 Word 可能无法正确计算差异。节属性修订Section properties 的 revision节属性页面大小、页边距、文字方向、分栏、垂直对齐、首页不同等的变更可以通过在节的properties对象中添加revision属性来追踪。与段落一样revision必须包含变更前的全部节属性值import { Document, Paragraph, TextRun, PageTextDirectionType } from docx; const doc new Document({ sections: [ { properties: { page: { textDirection: PageTextDirectionType.TOP_TO_BOTTOM_RIGHT_TO_LEFT, margin: { top: 2000, right: 1440, bottom: 1440, left: 1440, }, }, revision: { id: 11, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, page: { textDirection: PageTextDirectionType.LEFT_TO_RIGHT_TOP_TO_BOTTOM, margin: { top: 1440, right: 1440, bottom: 1440, left: 1440, }, }, }, }, children: [ new Paragraph({ children: [new TextRun(Section with changed text direction)], }), ], }, ], });该示例追踪了一次文字方向与页边距的变更当前节为“从上到下、从右到左”文字方向且上边距 2000revision记录变更前为“从左到右、从上到下”且上边距 1440底层对应w:sectPrChange元素。节属性修订适合在需要展示“版式调整历程”的场景下使用例如多版本页面布局的审阅。表格修订docx 库对表格的修订追踪支持非常全面分为表格属性、列宽、行、单元格四大类下面逐一说明。表格属性修订表格属性对齐方式、边框、宽度等的变更通过Table配置上的revision属性追踪revision 内包含变更前的属性值import { Table, TableRow, TableCell, Paragraph, AlignmentType } from docx; const table new Table({ rows: [ new TableRow({ children: [ new TableCell({ children: [new Paragraph(Cell 1)], }), ], }), ], alignment: AlignmentType.CENTER, revision: { id: 1, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, alignment: AlignmentType.RIGHT, }, });示例表达了“表格当前居中对齐变更前为右对齐”的一次对齐方式修订。表格列宽修订表格列宽的变更通过columnWidthsRevision属性追踪。它记录的是**网格列宽grid column widths**的变更需要同时提供当前列宽与变更前的列宽import { Table, TableRow, TableCell, Paragraph } from docx; const table new Table({ rows: [ new TableRow({ children: [ new TableCell({ children: [new Paragraph(Cell 1)], }), new TableCell({ children: [new Paragraph(Cell 2)], }), ], }), ], columnWidths: [1234, 321], columnWidthsRevision: { id: 1, columnWidths: [1000, 555], }, });这里columnWidths: [1234, 321]是当前两列的宽度columnWidthsRevision.columnWidths: [1000, 555]是变更前的宽度。注意columnWidthsRevision的示例中只包含了id与columnWidths字段未包含author/date在列宽修订的场景中Word 对网格变更的标记要求与文本修订略有不同使用时请以库的实际类型定义为准。表格行修订插入表格行标记一行被插入需要在TableRow配置上使用insertion属性同时行内单元格中的文本内容也必须通过段落的run.insertion属性或直接使用InsertedTextRun标记为插入。两者缺一不可Microsoft Word 只有在行级与内容级都标记为插入时才能正确显示该插入行import { TableRow, TableCell, Paragraph } from docx; const row new TableRow({ children: [ new TableCell({ children: [ new Paragraph({ children: [new TextRun(Inserted row)], run: { insertion: { id: 1, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, }, }, }), ], }), ], insertion: { id: 1, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, }, });删除表格行删除行与插入行对称使用deletion属性且同样要求行内文本通过段落run.deletion属性或DeletedTextRun标记为删除import { TableRow, TableCell, Paragraph } from docx; const row new TableRow({ children: [ new TableCell({ children: [ new Paragraph({ children: [new TextRun(Deleted row)], run: { deletion: { id: 2, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, }, }, }), ], }), ], deletion: { id: 2, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, }, });表格行属性修订行属性行高、表头行、不允许跨页断行等的变更通过revision属性追踪revision 内包含变更前的属性值import { TableRow, TableCell, Paragraph, HeightRule, CellSpacingType } from docx; const row new TableRow({ children: [ new TableCell({ children: [new Paragraph(Cell content)], }), ], height: { value: 200, rule: HeightRule.EXACT, }, tableHeader: false, revision: { id: 3, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, height: { value: 300, rule: HeightRule.EXACT, }, tableHeader: true, }, });示例追踪了一次“行高从 300 改为 200、并取消表头行属性”的修订当前height.value: 200tableHeader: falserevision内记录变更前的height.value: 300tableHeader: true。表格单元格修订插入表格单元格单元格的插入标记与行类似使用TableCell上的insertion属性并同时通过段落run.insertion或InsertedTextRun标记单元格内的文本内容import { TableCell, Paragraph } from docx; const cell new TableCell({ children: [ new Paragraph({ children: [new TextRun(Inserted cell)], run: { insertion: { id: 4, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, }, }, }), ], insertion: { id: 4, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, }, });删除表格单元格删除单元格使用deletion属性同样需要内容级标记run.deletion或DeletedTextRun配合import { TableCell, Paragraph } from docx; const cell new TableCell({ children: [ new Paragraph({ children: [new TextRun(Deleted cell)], run: { deletion: { id: 5, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, }, }, }), ], deletion: { id: 5, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, }, });表格单元格属性修订单元格属性垂直对齐、文字方向、边框、底纹等的变更通过revision属性追踪import { TableCell, Paragraph, VerticalAlignTable, TextDirection } from docx; const cell new TableCell({ children: [new Paragraph(Cell content)], verticalAlign: VerticalAlignTable.CENTER, textDirection: TextDirection.BOTTOM_TO_TOP_LEFT_TO_RIGHT, revision: { id: 6, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, verticalAlign: VerticalAlignTable.TOP, textDirection: TextDirection.LEFT_TO_RIGHT_TOP_TO_BOTTOM, }, });示例追踪了一次“垂直对齐从顶部改为居中、文字方向从水平改为自下而上”的单元格属性修订。单元格合并修订单元格纵向合并vertical merge的变更通过cellMerge属性追踪import { TableCell, Paragraph } from docx; const cell new TableCell({ children: [new Paragraph(Merged cell)], cellMerge: { id: 7, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, verticalMerge: cont, // or restart }, });关于verticalMerge的取值建议直接使用源码中导出的常量VerticalMergeRevisionType见 cell-merge.tsVerticalMergeRevisionType.CONTINUE值为cont表示与上方单元格合并延续与VerticalMergeRevisionType.RESTART值为rest表示从本单元格开始新的纵向合并。该常量在渲染层对应w:cellMerge元素及其w:vMerge/w:vMergeOrig属性。图片修订ImageRun 的 insertion 与 deletionImageRun也可以通过传入insertion或deletion属性标记为插入/删除的修订内容。库会将该图片 Run 包装进w:ins或w:del元素从而让 Word 以修订形式显示图片的增删import { Document, ImageRun, Paragraph, TextRun } from docx; import * as fs from fs; const doc new Document({ features: { trackRevisions: true, }, sections: [ { children: [ new Paragraph({ children: [ new TextRun(Inserted image: ), new ImageRun({ type: png, data: fs.readFileSync(./image.png), transformation: { width: 120, height: 120 }, insertion: { id: 30, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, }, }), ], }), new Paragraph({ children: [ new TextRun(Deleted image: ), new ImageRun({ type: png, data: fs.readFileSync(./image.png), transformation: { width: 120, height: 120 }, deletion: { id: 31, author: Firstname Lastname, date: 2020-10-06T09:00:00Z, }, }), ], }), ], }, ], });ImageRun的insertion/deletion选项与文本修订接受相同的属性PropertyTypeNotesDescriptionidnumberRequiredUnique revision IDauthorstringRequiredAuthor of the changedatestringRequiredISO 8601 timestamp of the change注意一个ImageRun只能带有insertion或deletion其中之一不能同时设置两者如果两者都没有提供图片将正常渲染、不带任何修订标记。完整的图片修订演示可参考 demo/103-track-change-images.ts它使用demo/images/dog.png构造了一个“插入图片 删除图片”的文档并在生成后输出101-track-change-images.docx。完整可运行示例官方 demo 提供了两个与本主题直接相关的可运行示例是理解本文全部 API 的最佳配套材料demo/60-track-revisions.ts文本修订的完整示例覆盖InsertedTextRun/DeletedTextRun在正文、脚注、页脚中的应用包括带格式的删除 Run颜色、粗体、字号、字体、底纹、revision样式修订、页码字段的增删以及features.trackRevisions开关最终通过Packer.toBuffer输出My Document.docxdemo/103-track-change-images.ts图片修订的完整示例展示了ImageRun的insertion/deletion用法并输出101-track-change-images.docx。运行示例时只需将文件置于项目环境内并执行对应的 TypeScript 编译/运行脚本即可生成带修订标记的 Word 文档随后在 Microsoft Word 中打开即可看到插入内容通常以带下划线着色文本呈现与删除内容通常以删除线文本呈现的审阅效果。小结docx 库的修订追踪能力覆盖了从文本、样式、段落、节到表格与图片的完整文档元素层级文本级用InsertedTextRun/DeletedTextRun格式与属性级用各类revision属性其核心约定是“revision 内必须包含变更前的完整属性快照”结构性增删表格行、单元格、图片用insertion/deletion标记全局自动追踪用features.trackRevisions。理解这些 API 背后的w:ins/w:del/w:trackRevisions以及各*Change元素如w:pPrChange、w:sectPrChange、w:cellMerge能帮助你在生成合同时效仿 Word 原生审阅体验为文档协作、版本比对等场景提供开箱即用的能力。【免费下载链接】docxEasily generate and modify .docx files with JS/TS with a nice declarative API. Works for Node and on the Browser.项目地址: https://gitcode.com/GitHub_Trending/do/docx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/17 9:24:18

可灵Kling AI实操指南:文生视频、运动笔刷与提示词避坑全攻略

可灵Kling AI的发布推文我第一时间刷到了,当时评论区已经吵成一片:有人问怎么申请、有人晒生成效果、还有人在催排队体验资格。说实话,从可灵AI在2024年6月正式亮相开始,我就一直在跟这条产品线,每次官方但凡放出点新动…

2026/9/17 9:24:18

电商数据分析实战:从埋点到决策的完整闭环

1. 电商数据分析的底层逻辑与价值闭环在杭州某头部电商平台担任数据团队负责人的第五年,我逐渐摸清了电商数据分析的黄金法则——数据本身不会创造价值,只有当分析结果真正影响运营决策时,数据才产生商业意义。去年双十一大促期间&#xff0c…

2026/9/17 9:24:18

DeepSeek API 调用、本地部署与工具链接入实战

简介:《2025 DeepSeek自学手册》以73页PDF呈现,面向希望系统掌握DeepSeek V3与R1的AI初学者、开发者及研究人员。内容从模型起源、架构设计与性能表现切入,延伸到提示词技巧、数据处理、微调及无监督、监督与强化学习实现路径,并以…

2026/9/17 10:39:29

LLM辅助测试用例生成:从PRD到可落地用例的完整实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/17 10:39:29

Keil MDK 5.39安装配置与STM32调试:从零搭建嵌入式开发环境

每年总有一批人从 51 转到 STM32,第一步不是学寄存器,也不是看数据手册,而是先和 Keil 干一架。下载渠道五花八门,装完编译各种报错,好不容易编过了又识别不到 ST-Link,新手三分之一的时间都消耗在这套工具…

2026/9/17 10:39:29

从Modbus到EtherCAT:个人开发者啃透12种工控协议指南

去年年初,我接了一个汽配厂的设备数据采集项目。合同签完,兴冲冲进了车间,看到现场的设备清单直接傻眼:西门子S7-1200、三菱FX5U、台达变频器、国产电表、楼宇温控器……每一类设备的通信协议都不一样,有些甚至让我听都…

2026/9/17 10:39:29

语义通信高斯信道仿真指南:端到端训练与AWGN建模实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/16 12:52:37

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/17 0:03:13

WiFi密码安全测试:从原理到实战的字典暴力破解指南

1. 写在前面:我为什么要研究WiFi密码这件事先交代一下背景。我身边有不少朋友,家里的WiFi密码常年是"12345678"或者"88888888",问就是"好记"。直到有一次,隔壁邻居蹭网蹭到我家路由器后台都进不去&…

2026/9/17 0:03:13

redis-py服务控制与监控函数实战:从ping到slowlog的巡检指南

我用 redis-py 写了快五年的业务代码,坦白说,真正让我觉得这个客户端“像一个成熟工具箱”的,不是 get/set 那套基本操作,而是它那批专门做服务控制与状态监控的辅助函数。日常开发里,大家把redis.Redis(host..., deco…

2026/9/17 0:03:13

SpringBoot+Vue3实现中小企业设备管理系统开发实践

1. 项目概述与核心价值中小企业设备管理系统是制造业、服务业等领域的基础信息化工具。传统设备管理往往依赖Excel表格或纸质记录,存在数据孤岛、流程混乱、维护成本高等痛点。这套基于Java SpringBootVue3MyBatis的技术方案,通过前后端分离架构实现了设…

2026/9/16 22:55:57

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/16 22:56:09

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/16 22:56:16

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码