批注是 Word 文档协作中不可或缺的功能,广泛用于审阅、校对和团队讨论场景。Spire.Doc for JavaScript 基于 WebAssembly 在浏览器端直接完成批注的读写操作,通过虚拟文件系统(VFS)管理文档文件,无需后端服务支持,也无需安装 Microsoft Word。
本文介绍三个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.Doc for JavaScript。以下示例默认已安装 Spire.Doc 并完成 WebAssembly 模块初始化。
添加批注到指定文本
在实际文档审阅场景中,我们经常需要针对文档中的某段特定文字添加批注。实现思路是:首先通过 FindString 方法搜索定位目标文本,然后在该文本的前后分别插入 CommentMarkStart 和 CommentMarkEnd 标记,最后将 Comment 对象添加到段落中,从而将批注与指定文本关联起来。
import React from 'react';
function App() {
const AddCommentForSpecificText = async () => {
// 获取 Spire.Doc WASM 模块
const docModule = window.wasmModule?.spiredoc;
// 检查模块是否就绪
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 将目标 Word 文档载入 VFS
const inputFileName = "CommentTemplate.docx";
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// 创建 Document 实例并加载文档
let doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// 调用自定义函数,为指定文本添加批注
InsertComments(doc, "办公室", docModule);
// 保存文档
const outputFileName = "AddCommentForSpecificText.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
// 释放资源
doc.Dispose();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
// 自定义函数:为指定关键词添加批注
function InsertComments(doc, keystring, wasmModule) {
// 在文档中查找目标字符串
let find = doc.FindString(keystring, false, true);
// 创建批注起始标记和结束标记
let commentMarkStart = new wasmModule.CommentMark(doc, 1, wasmModule.CommentMarkType.CommentStart);
let commentMarkEnd = new wasmModule.CommentMark(doc, 1, wasmModule.CommentMarkType.CommentEnd);
// 创建批注对象,设置内容和作者
let comment = new wasmModule.Comment(doc);
comment.Body.AddParagraph().Text = "测试评论";
comment.Format.Author = "Administrator";
// 获取查找到的文本范围及其所在段落
let range = find.GetAsOneRange();
let para = range.OwnerParagraph;
// 获取文本范围在段落中的索引位置
let index = para.ChildObjects.IndexOf(range);
// 将批注添加到段落
para.ChildObjects.Add(comment);
// 在目标文本前后插入批注起始和结束标记
para.ChildObjects.Insert(index, commentMarkStart);
para.ChildObjects.Insert(index + 2, commentMarkEnd);
}
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>为特定文本添加评论。</h1>
<button onClick={AddCommentForSpecificText}>
Generate
</button>
</div>
);
};
export default App;
通过上述代码,可以在文档中搜索到指定关键词后,在其位置插入批注标记,从而实现将批注精准地添加到特定文本上。

提取文档中的批注
当文档经过多人审阅后,往往包含大量批注。批量提取这些批注内容,便于汇总审阅意见或进行后续处理。Spire.Doc 提供了 Comments 集合,我们可以遍历该集合逐一读取每条批注的正文内容,然后导出为文本文件。
import React from 'react';
function App() {
const ExtractComment = async () => {
// 获取 Spire.Doc WASM 模块
const docModule = window.wasmModule?.spiredoc;
// 检查模块是否就绪
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 将目标 Word 文档载入 VFS
const inputFileName = "CommentSample.docx";
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// 创建 Document 实例并加载文档
let doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// 遍历所有批注,提取文本内容
let SB = [];
for (let i = 0; i < doc.Comments.Count; i++) {
let comment = doc.Comments.get_Item(i);
for (let j = 0; j < comment.Body.Paragraphs.Count; j++) {
let p = comment.Body.Paragraphs.get_Item(j);
SB.push(p.Text + "\n");
}
}
// 将提取的批注内容保存为文本文件
const outputFileName = 'ExtractComment.txt';
const blob = new Blob([SB.toString()], { type: "text/plain;charset=utf-8" });
// 释放资源
doc.Dispose();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>从文档中提取评论。</h1>
<button onClick={ExtractComment}>
Generate
</button>
</div>
);
};
export default App;
通过 doc.Comments 集合可以访问文档中的所有批注,每条批注的正文内容通过 comment.Body.Paragraphs 获取。提取后的内容可以保存为纯文本文件,方便汇总查阅或导入其他系统。

回复批注与修改批注
在团队协作场景中,对已有批注进行回复和内容修正是常见的需求。Spire.Doc 支持通过 ReplyToComment 方法为批注添加回复,同时也支持修改批注内容或删除不需要的批注。以下示例演示了如何获取文档中的第一个批注,为其添加一条带图片的回复内容。
import React from 'react';
function App() {
const ReplyToComment = async () => {
// 获取 Spire.Doc WASM 模块
const docModule = window.wasmModule?.spiredoc;
// 检查模块是否就绪
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 将目标文档和图片载入 VFS
const inputFileName = "Comment.docx";
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
const imageFile = "logo.png";
await window.spire.FetchFileToVFS(imageFile, '', `${process.env.PUBLIC_URL}/data/`);
// 创建 Document 实例并加载文档
let doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// 获取文档中的第一个批注
let comment1 = doc.Comments.get_Item(0);
// 创建回复批注,设置作者和内容
let replyComment1 = new docModule.Comment(doc);
replyComment1.Format.Author = "E-iceblue";
replyComment1.Body.AddParagraph().AppendText("Spire.Doc is a professional Word library for operating Word documents.");
// 将回复批注添加到原始批注
comment1.ReplyToComment(replyComment1);
// 加载图片并插入到回复批注中
let docPicture = new docModule.DocPicture(doc);
docPicture.LoadImage(imageFile);
replyComment1.Body.Paragraphs.get_Item(0).ChildObjects.Add(docPicture);
// 保存文档
const outputFileName = "ReplyToComment.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx });
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
// 释放资源
doc.Dispose();
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>添加回复评论。</h1>
<button onClick={ReplyToComment}>
Generate
</button>
</div>
);
};
export default App;
除了回复批注外,还可以通过 Comments.RemoveAt(index) 方法删除指定批注,或通过 Body.Paragraphs.get_Item(0).Replace(...) 修改批注中的文本内容:
// 修改第一个批注的内容
doc.Comments.get_Item(0).Body.Paragraphs.get_Item(0)
.Replace({ given: "原文本", replace: "修改后的文本", caseSensitive: false, wholeWord: false });
// 删除第二个批注
doc.Comments.RemoveAt(1);

常见问题
批注添加后无法在 Word 中正常显示
原因:批注标记 CommentMarkStart 和 CommentMarkEnd 的插入位置不正确,或 Comment 对象未正确添加到段落中。批注的起始标记必须位于被批注文本之前,结束标记位于被批注文本之后,且 Comment 对象本身也需要添加到同一段落中。
解决:确保按正确顺序操作——先获取目标文本的索引位置,然后依次插入 CommentMarkStart、将 Comment 添加到段落末尾,最后在文本后插入 CommentMarkEnd。
提取批注时输出为空
原因:文档中可能不存在批注,或者批注内容存储在嵌套结构中。另外,如果文档加载时路径错误或文件未成功载入 VFS,也会导致无法读取批注。
解决:提取前先检查 doc.Comments.Count 是否大于 0,确认文档中包含批注。同时确保通过 FetchFileToVFS 正确加载了文档文件:
await window.spire.FetchFileToVFS(
'CommentSample.docx', '', `${process.env.PUBLIC_URL}/static/data/`
);
回复批注后原批注丢失
原因:ReplyToComment 方法的调用对象是原始批注,如果误将回复批注作为调用对象,或者调用了多次导致引用混乱,可能导致批注结构异常。
解决:确保始终以文档中已有的原始批注对象调用 ReplyToComment 方法,新创建的 Comment 对象作为参数传入:
// 正确:原始批注调用 ReplyToComment,新批注作为参数
existingComment.ReplyToComment(replyComment);
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







