书签是 word 文档中一种不可见的定位标记,它充当文档中的"坐标",能够精确标记某个位置或一段文本范围。但书签的真正价值不仅在于定位——通过编程手段获取书签范围内的内容、替换其中的占位文本、删除不再需要的内容,或在书签位置插入文本、段落、表格和图片,开发者可以实现合同模板的自动填充、报告数据的动态注入、表单内容的批量清理等高级文档处理流程。可以说,围绕着书签内容"读、写、删、插"的操作组合,构成了 word 自动化的核心工作流。
spire.doc for javascript 基于 webassembly 在浏览器端直接完成书签内容的读取、替换、删除以及元素插入操作,通过虚拟文件系统(vfs)管理文件,无需后端j9官方网址的服务支持。
本文介绍四个核心功能点:
有关安装和项目配置,请参考 。以下示例默认已安装 spire.doc 并完成 webassembly 模块初始化。
获取书签内容
获取书签内容是对书签进行任何操作的前提。通过 bookmarksnavigator 定位到指定书签后,getbookmarkcontent 方法将书签范围内的内容作为 textbodypart 对象返回,开发者可以遍历其 bodyitems 集合下的元素进行获取。
function app() {
const bookmarkcontent = async () => {
// 获取 spire.doc wasm 模块
const docmodule = window.wasmmodule?.spiredoc;
// 检查 wasm 模块是否已加载完成
if (!docmodule) {
alert('spire.doc is not ready yet');
return;
}
// 将 word 文档载入虚拟文件系统(vfs)
const inputfilename = '合同模板.docx';
await window.spire.fetchfiletovfs(inputfilename, '', `${process.env.public_url}/data/`);
// 加载 word 文档
const doc = new docmodule.document();
doc.loadfromfile(inputfilename);
// 创建 bookmarksnavigator 并定位到书签
let navigator = new docmodule.bookmarksnavigator(doc);
navigator.movetobookmark("合同书签");
let textbodypart = navigator.getbookmarkcontent();
// 迭代书签内容中的元素,提取文本
let text = "";
for (let i = 0; i < textbodypart.bodyitems.count; i ) {
let item = textbodypart.bodyitems.get_item(i);
if (item instanceof docmodule.paragraph) {
for (let j = 0; j < item.childobjects.count; j ) {
let childobject = item.childobjects.get_item(j);
if (childobject instanceof docmodule.textrange) {
text = childobject.text;
}
}
}
}
// 保存为 .txt 文件
const outputfilename = "获取的内容.txt";
// txt 文件保存到 vfs 并触发下载
window.dotnetruntime.module.fs.writefile(outputfilename, text);
const filearray = window.dotnetruntime.module.fs.readfile(outputfilename);
const blob = new blob([filearray], { type: 'text/plain' });
const url = url.createobject;
const a = document.createelement('a');
a.href = url;
a.download = outputfilename;
a.click();
url.revokeobject;
// 释放资源
doc.dispose();
};
return (
在 react 中使用 javascript 获取、替换、删除 word 书签内容并插入元素-j9官方网址
);
}
export default app;
执行上述代码,将把书签"合同书签"范围内的文本内容提取并保存为独立的 .txt 文件:

替换书签内容
替换书签内容是在文档模板填充中最常用的操作。通过 bookmarksnavigator 定位到书签后,调用replacebookmarkcontent 方法不仅支持替换为纯文本,还支持替换为表格等复杂元素,适合在合同生成、报表填充等场景中替换占位符。
function app() {
const replacebookmarkcontent = async () => {
// 获取 spire.doc wasm 模块
const docmodule = window.wasmmodule?.spiredoc;
// 检查 wasm 模块是否已加载完成
if (!docmodule) {
alert('spire.doc is not ready yet');
return;
}
// 将字体和 word 文件载入 vfs
await window.spire.fetchfiletovfs('simsun.ttc', '/library/fonts/', `${process.env.public_url}/font/`);
const inputfilename = '书签文档.docx';
await window.spire.fetchfiletovfs(inputfilename, '', `${process.env.public_url}/data/`);
// 加载 word 文档
const doc = new docmodule.document();
doc.loadfromfile(inputfilename);
// 创建 bookmarksnavigator 并定位到书签
let navigator = new docmodule.bookmarksnavigator(doc);
navigator.movetobookmark("书签1");
// 替换“书签1”的内容——用文本替换
navigator.replacebookmarkcontent({ text: "这是替换到书签的文本", saveformatting: true });
// 继续替换"书签2"的内容——用表格替换
navigator.movetobookmark("书签2");
// 创建表格
let table = new docmodule.table(doc, true);
table.resetcells(4, 5);
// 创建数据表并将数据填充到表格中
let dt = [
["城市", "省份", "人口", "面积(km²)", "简称"],
["北京", "北京", "2189万", "16410", "京"],
["上海", "上海", "2475万", "6340", "沪"],
["广州", "广东", "1867万", "7434", "穗"]];
for (let i = 0; i < 4; i ) {
for (let j = 0; j < 5; j ) {
table.rows.get_item(i).cells.get_item(j).addparagraph().appendtext(dt[i][j]);
}
}
// 创建 textbodypart 实例并将表格添加到其中
let part = new docmodule.textbodypart({ doc: doc });
part.bodyitems.add(table);
// 用 textbodypart 对象替换当前书签内容
navigator.replacebookmarkcontent({ bodypart: part });
// 保存为新的 .docx 文件
const outputfilename = "替换书签.docx";
doc.savetofile({ filename: outputfilename, fileformat: docmodule.fileformat.docx2013 });
// 从 vfs 读取生成的文件并触发下载
const filearray = window.dotnetruntime.module.fs.readfile(outputfilename);
const blob = new blob([filearray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = url.createobject;
const a = document.createelement('a');
a.href = url;
a.download = outputfilename;
a.click();
url.revokeobject;
// 释放资源
doc.dispose();
};
return (
);
}
export default app;
此方式可以替换书签内容为纯文本,也支持替换为表格等复杂元素。书签标记本身在替换后仍然保留,便于后续再次定位。执行效果如下图所示:

删除书签内容
删除书签内容与删除书签标记是两个不同的操作。通过 bookmarksnavigator 定位到书签后,调用 deletebookmarkcontent 方法可以移除书签范围内的文本内容,但保留书签标记本身,以便后续重新填入内容。如果只需清空内容而保留定位标记,此方法是首选。
function app() {
const deletebookmarkcontent = async () => {
// 获取 spire.doc wasm 模块
const docmodule = window.wasmmodule?.spiredoc;
// 检查 wasm 模块是否已加载完成
if (!docmodule) {
alert('spire.doc is not ready yet');
return;
}
// 将 word 文件载入 vfs
const inputfilename = '合同模板.docx';
await window.spire.fetchfiletovfs(inputfilename, '', `${process.env.public_url}/data/`);
// 加载 word 文档
const doc = new docmodule.document();
doc.loadfromfile(inputfilename);
// 创建 bookmarksnavigator 并定位到书签
let navigator = new docmodule.bookmarksnavigator(doc);
navigator.movetobookmark("合同书签");
// 删除书签内容,保留书签标记
navigator.deletebookmarkcontent(true);
// 保存为新的 .docx 文件
const outputfilename = "删除书签内容.docx";
doc.savetofile({ filename: outputfilename, fileformat: docmodule.fileformat.docx2013 });
// 从 vfs 读取生成的文件并触发下载
const filearray = window.dotnetruntime.module.fs.readfile(outputfilename);
const blob = new blob([filearray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = url.createobject;
const a = document.createelement('a');
a.href = url;
a.download = outputfilename;
a.click();
url.revokeobject;
// 释放资源
doc.dispose();
};
return (
);
}
export default app;
使用
deletebookmarkcontent删除的是书签范围内的文本内容,书签标记本身仍然保留;而bookmarks.remove移除的是书签标记,范围内的文本不受影响。
执行后文档中书签"合同书签"范围内的文本被移除,但书签标记仍保留在文档中:

在书签位置插入文本、段落、表格和图片
spire.doc 支持在书签位置灵活插入多种类型的文档元素。提供 inserttext、insertparagraph、inserttable 等方法插入文本、段落和表格。同时也可以根据书签起始节点在段落 childobjects 中的索引来插入多种元素。
function app() {
const insertelementsatbookmark = async () => {
// 获取 spire.doc wasm 模块
const docmodule = window.wasmmodule?.spiredoc;
// 检查 wasm 模块是否已加载完成
if (!docmodule) {
alert('spire.doc is not ready yet');
return;
}
// 加载字体和 word 文档到 vfs
await window.spire.fetchfiletovfs('msyh.ttc', '/library/fonts/', `${process.env.public_url}/font/`);
const inputfilename = '书签文档.docx';
await window.spire.fetchfiletovfs(inputfilename, '', `${process.env.public_url}/data/`);
// 创建 document 对象并加载文档
const doc = new docmodule.document();
doc.loadfromfile(inputfilename);
// 定位到书签位置
let navigator = new docmodule.bookmarksnavigator(doc);
navigator.movetobookmark("书签1");
// 1. 插入文本
navigator.inserttext("这是插入的文本内容。", true);
// 2. 插入段落
let newparagraph = new docmodule.paragraph(doc);
newparagraph.appendtext("这是插入的段落内容。")
navigator.movetobookmark("书签2");
navigator.insertparagraph(newparagraph);
// 3. 插入表格 — 2 行 3 列
let table = new docmodule.table(doc, true);
table.resetcells(2, 3);
table.rows.get_item(0).cells.get_item(0).addparagraph().appendtext("名称");
table.rows.get_item(0).cells.get_item(1).addparagraph().appendtext("数量");
table.rows.get_item(0).cells.get_item(2).addparagraph().appendtext("备注");
table.rows.get_item(1).cells.get_item(0).addparagraph().appendtext("产品 a");
table.rows.get_item(1).cells.get_item(1).addparagraph().appendtext("100");
table.rows.get_item(1).cells.get_item(2).addparagraph().appendtext("已入库");
navigator.movetobookmark("书签3");
navigator.inserttable(table);
// 4. 插入图片
const imagefilename = '图片.png';
await window.spire.fetchfiletovfs(imagefilename, '', `${process.env.public_url}/data/`);
let picture = new docmodule.docpicture(doc);
picture.loadimage(imagefilename);
picture.width = 100;
picture.height = 200;
navigator.movetobookmark("书签4");
// 获取书签起始节点
let start = navigator.currentbookmark.bookmarkstart;
// 获取书签所在的段落
let bookmarkpara = start.ownerparagraph;
// 获取书签起始节点在段落中的索引位置
let startindex = bookmarkpara.childobjects.indexof(start);
// 在书签起始节点后插入图片
bookmarkpara.childobjects.insert(startindex 1, picture);
// 保存文档为 .docx 格式
const outputfilename = "插入元素到书签.docx";
doc.savetofile({ filename: outputfilename, fileformat: docmodule.fileformat.docx2013 });
// 从 vfs 读取生成的文件并触发下载
const filearray = window.dotnetruntime.module.fs.readfile(outputfilename);
const blob = new blob([filearray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = url.createobject;
const a = document.createelement('a');
a.href = url;
a.download = outputfilename;
a.click();
url.revokeobject;
// 释放 document 资源
doc.dispose();
};
return (
);
}
export default app;
执行上述代码,将在书签处插入文本、新段落、表格和图片,原有内容不会被覆盖:

常见问题
替换书签内容后,原来的字体、字号、颜色等格式丢了怎么办?
replacebookmarkcontent 默认会用纯文本替换,原格式会丢失。如果需要保留书签原有的格式,传入 saveformatting: true:
navigator.replacebookmarkcontent({ text: "新内容", saveformatting: true });
这样替换后的文本会沿用书签原来的字体、字号、颜色等格式。
如何批量处理文档中的多个书签?
遍历 doc.bookmarks 集合,逐个定位并操作:
for (let i = 0; i < doc.bookmarks.count; i ) {
let bookmark = doc.bookmarks.get_item(i);
navigator.movetobookmark(bookmark.name);
// 执行替换、删除或插入操作
}
deletebookmarkcontent 和直接删除书签标记有什么区别?
deletebookmarkcontent:只清空书签范围内的内容,书签标记保留在文档中,后续仍可通过书签名称定位并填入新内容。bookmarks.remove:移除书签标记本身,书签范围内的内容不受影响,但书签名称会消失,无法再定位。
两者互补,根据需求选择:需要保留"占位"能力就用 deletebookmarkcontent,不需要书签了就移除标记。
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用javascript。获取有效期 30 天的临时许可证。




