书签是 Word 文档中用于标记特定位置或内容范围的命名锚点,向书签内写入内容可以让业务数据自动落到模板的指定位置,而无需关心文档的实际排版。Spire.Doc for JavaScript 基于 WebAssembly 在浏览器端直接完成此操作,通过虚拟文件系统(VFS)管理字体、文档与图片资源,无需后端服务支持。
本文介绍两个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.Doc for JavaScript。以下示例默认已安装 Spire.Doc 并完成 WebAssembly 模块初始化。
向书签位置插入文档内容
向书签内插入文档内容的核心流程分为三个阶段:首先实例化两个 Document 分别加载文件,然后使用 BookmarksNavigator.MoveToBookmark 按名称定位书签,通过 CurrentBookmark.BookmarkStart 取得书签的起始标记,再由 OwnerParagraph 与 IndexOf 得到书签所在段落在节中的索引,最后把来源文档的段落逐个 Clone() 后插入到该索引之后;最后保存文档并从 VFS 读取生成的文件,封装为 Blob 后触发浏览器下载。
function App() {
const InsertDocAtBookmark = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 将待填充的目标文档载入 VFS
let inputFileName_1 = "InsertDocAtBookmark1.docx";
await window.spire.FetchFileToVFS(inputFileName_1, "", `${process.env.PUBLIC_URL}/static/data/`);
// 将提供内容的来源文档载入 VFS
let inputFileName_2 = "InsertDocAtBookmark2.docx";
await window.spire.FetchFileToVFS(inputFileName_2, "", `${process.env.PUBLIC_URL}/static/data/`);
// 加载目标文档
let document1 = new docModule.Document();
document1.LoadFromFile(inputFileName_1);
// 加载来源文档
let document2 = new docModule.Document();
document2.LoadFromFile(inputFileName_2);
// 获取目标文档的第一节
let section1 = document1.Sections.get_Item();
// 创建书签导航器,用于定位书签
let bn = new docModule.BookmarksNavigator(document1);
// 按名称查找书签
bn.MoveToBookmark("Test", true, true);
// 获取书签的起始标记
let start = bn.CurrentBookmark.BookmarkStart;
// 获取起始标记所在的段落
let para = start.OwnerParagraph;
// 获取该段落在节中的索引
let index = section1.Body.ChildObjects.IndexOf(para);
// 将来源文档的段落依次插入到书签所在段落之后
for (let i = 0; i < document2.Sections.Count; i++) {
let section2 = document2.Sections.get_Item(i);
for (let j = section2.Paragraphs.Count-1; j >=0; j--) {
let paragraph = section2.Paragraphs.get_Item(j);
section1.Body.ChildObjects.Insert(index + 1, paragraph.Clone());
}
}
// 定义输出文件名
const outputFileName = "InsertDocAtBookmark-result.docx";
// 保存文档
document1.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
document1.Dispose();
document2.Dispose();
// 读取保存的文件并转换为 Blob 对象
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], {type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"});
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>在 Word 文档的书签位置插入文档</h1>
<button onClick={InsertDocAtBookmark}>开始</button>
</div>
);
}
export default App;
来源文档中的段落被插入到书签所在位置后生成的 Word 输出

向书签位置插入图片
书签定位的是文档中的一个位置,因此它同样可以承载图片这类非文本内容,例如向合同模板的签章书签处插入印章图片。核心流程分为三个阶段:首先实例化 Document 加载文件,然后用 BookmarksNavigator 定位书签,通过 AddSection 创建一个临时节,在临时节中新增段落并用 AppendPicture 把图片追加到段落中,再用 InsertParagraph 将该段落整体插入到书签位置,最后移除临时节;最后保存文档并从 VFS 读取生成的文件,封装为 Blob 后触发浏览器下载。
function App() {
const InsertImageAtBookmark = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 将目标文档载入 VFS
let inputFileName = "InsertImageAtBookmark.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/static/data/`);
// 将待插入的图片载入 VFS
let imageFileName = "Word.png";
await window.spire.FetchFileToVFS(imageFileName, "", `${process.env.PUBLIC_URL}/static/data/`);
// 加载文档
let doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// 创建书签导航器,用于定位书签
let bn = new docModule.BookmarksNavigator(doc);
// 按名称查找书签
bn.MoveToBookmark("Test", true, true);
// 新增一个临时节,用于承载图片段落
let section0 = doc.AddSection();
// 在临时节中新增一个段落
let paragraph = section0.AddParagraph();
// 将图片追加到段落中
paragraph.AppendPicture({ imgFile: imageFileName });
// 将该段落插入到书签位置
bn.InsertParagraph(paragraph);
// 移除临时节
doc.Sections.Remove(section0);
// 定义输出文件名
const outputFileName = "InsertImageAtBookmark-result.docx";
// 保存文档
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
doc.Dispose();
// 读取保存的文件并转换为 Blob 对象
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], {type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"});
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>在 Word 文档的书签位置插入图片</h1>
<button onClick={InsertImageAtBookmark}>开始</button>
</div>
);
}
export default App;
图片被插入到书签所在位置后生成的 Word 输出

常见问题
提示找不到书签,MoveToBookmark 无法定位
原因:MoveToBookmark 按书签名称定位,名称区分大小写,且必须与文档中实际的书签名完全一致。若名称拼写不匹配,或目标文档中根本不存在该名称的书签,定位就会失败。
解决:定位前先遍历 Bookmarks 集合确认文档中的书签名称,再传入准确的书签名:
// 遍历文档中的所有书签,确认名称是否匹配
for (let i = 0; i < doc.Bookmarks.Count; i++) {
console.log(doc.Bookmarks.get_Item(i).Name);
}
// 确认书签存在后按准确名称定位
let bn = new wasmModule.BookmarksNavigator(doc);
bn.MoveToBookmark("Test", true, true);
插入的图片尺寸超出页面
原因:AppendPicture 按图片的原始像素尺寸插入,不会自动适配页面宽度。若图片分辨率远高于页面可用宽度,插入后会溢出页面或撑开原有版式。
解决:AppendPicture 会返回图片对象,可在插入到书签位置前按最大宽度等比缩放(Width、Height 的单位为磅):
// 追加图片并保留返回的图片对象
let paragraph = section0.AddParagraph();
let picture = paragraph.AppendPicture({ imgFile: imageFileName });
// 按最大宽度等比缩放
let maxWidth = 400;
if (picture.Width > maxWidth) {
picture.Height = picture.Height * (maxWidth / picture.Width);
picture.Width = maxWidth;
}
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







