在文档管理系统中,拆分 Word 文档是一个常见需求——将合并后的多章节文档按分节符拆分为独立文件,或将长文档按分页符分割为多个短文档。Spire.Doc for JavaScript 基于 WebAssembly 在浏览器端直接完成文档拆分,通过虚拟文件系统(VFS)管理输入输出文件,无需后端服务支持。
本文介绍两个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.Doc for JavaScript。以下示例默认已安装 Spire.Doc 并完成 WebAssembly 模块初始化。
按分节符拆分
Word 文档中的分节符(Section Break)用于分隔不同章节或版面布局,每个节可以拥有独立的页眉页脚、页码格式和页面设置。按分节符拆分是最常用、最稳定的拆分方式,适用于将合并后的多章节文档还原为独立文件。
核心流程分为三个阶段:首先将字体文件和目标 Word 文件载入 WASM 虚拟文件系统;然后实例化 Document 加载文件,遍历所有节,通过 Section.Clone() 将每个节克隆到新的 Document 对象中;最后将拆分后的文件打包为 ZIP 触发浏览器下载。
function App() {
const splitBySectionBreak = async () => {
// 获取 Spire.Doc WASM 模块
const docModule = window.wasmModule?.spiredoc;
// 检查模块是否就绪
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
const inputFileName = 'Template_Docx_4.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// 创建输出目录
let outputDir = 'output/';
window.dotnetRuntime.Module.FS.mkdirTree(outputDir);
// 加载文档
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// 遍历每个节,克隆为独立文档
for (let i = 0; i < doc.Sections.Count; i++) {
const newWord = new docModule.Document();
newWord.Sections.Add(doc.Sections.get_Item(i).Clone());
newWord.SaveToFile({
fileName: outputDir + `Section-${i}.docx`,
fileFormat: docModule.FileFormat.Docx2013
});
newWord.Dispose();
}
doc.Dispose();
// 从 VFS 读取输出文件,打包为 ZIP 下载
const JSZip = require('jszip');
const zip = new JSZip();
let items = window.dotnetRuntime.Module.FS.readdir(outputDir);
items = items.filter(item => item !== '.' && item !== '..');
for (const item of items) {
const fileData = window.dotnetRuntime.Module.FS.readFile(outputDir + item);
zip.file(item, fileData);
}
const zipBlob = await zip.generateAsync({ type: 'blob' });
const url = URL.createObjectURL(zipBlob);
const a = document.createElement('a');
a.href = url;
a.download = 'SplitBySectionBreak.zip';
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Split Word Document By Section Break</h1>
<button onClick={splitBySectionBreak}>Generate</button>
</div>
);
}
export default App;
按分节符拆分后生成的独立 Word 文档

按分页符拆分
分页符(Page Break)是文档中手动插入或自动生成的分页标记。按分页符拆分适用于将长篇文档按页分割,每页内容保存为一个独立文档,常用于报告分页、合同条款拆分等场景。
与按分节符拆分不同,分页符位于段落内部的子对象层级,需要逐层遍历文档的节(Section)、段落(Paragraph)以及段落子对象,检测 Break 类型为 PageBreak 的元素。拆分时还需通过 CloneDefaultStyleTo、CloneThemesTo、CloneCompatibilityTo 等方法克隆原文档的样式和主题,确保拆分后的文档格式完整。
function App() {
const splitByPageBreak = async () => {
// 获取 Spire.Doc WASM 模块
const docModule = window.wasmModule?.spiredoc;
// 检查模块是否就绪
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
const inputFileName = 'SplitWordFileByPageBreak.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// 创建输出目录
let outputDir = 'output/';
window.dotnetRuntime.Module.FS.mkdirTree(outputDir);
// 加载文档
const original = new docModule.Document();
original.LoadFromFile(inputFileName);
// 创建新文档,克隆样式和主题
let newWord = new docModule.Document();
let section = newWord.AddSection();
original.CloneDefaultStyleTo(newWord);
original.CloneThemesTo(newWord);
original.CloneCompatibilityTo(newWord);
let index = 0;
// 遍历所有节
for (let i = 0; i < original.Sections.Count; i++) {
let sec = original.Sections.get_Item(i);
// 遍历节中的所有子对象(段落、表格等)
for (let j = 0; j < sec.Body.ChildObjects.Count; j++) {
let obj = sec.Body.ChildObjects.get_Item(j);
if (obj instanceof docModule.Paragraph) {
let para = obj;
sec.CloneSectionPropertiesTo(section);
section.Body.ChildObjects.Add(para.Clone());
// 检测段落中的分页符
for (let k = 0; k < para.ChildObjects.Count; k++) {
let parobj = para.ChildObjects.get_Item(k);
if (parobj instanceof docModule.Break &&
parobj.BreakType === docModule.BreakType.PageBreak) {
let breakIndex = para.ChildObjects.IndexOf(parobj);
// 从段落中移除分页符
section.Body.LastParagraph.ChildObjects.RemoveAt(breakIndex);
// 保存当前文档
newWord.SaveToFile({
fileName: outputDir + `Page-${index}.docx`,
fileFormat: docModule.FileFormat.Docx2013
});
index++;
// 创建新文档继续
newWord = new docModule.Document();
section = newWord.AddSection();
original.CloneDefaultStyleTo(newWord);
original.CloneThemesTo(newWord);
original.CloneCompatibilityTo(newWord);
sec.CloneSectionPropertiesTo(section);
// 处理分页符后的剩余内容
section.Body.ChildObjects.Add(para.Clone());
if (section.Paragraphs.get_Item(0).ChildObjects.Count === 0) {
section.Body.ChildObjects.RemoveAt(0);
} else {
while (breakIndex >= 0) {
section.Paragraphs.get_Item(0).ChildObjects.RemoveAt(breakIndex);
breakIndex--;
}
}
}
}
}
if (obj instanceof docModule.Table) {
section.Body.ChildObjects.Add(obj.Clone());
}
}
}
// 保存最后一份文档
newWord.SaveToFile({
fileName: outputDir + `Page-${index}.docx`,
fileFormat: docModule.FileFormat.Docx2013
});
original.Dispose();
newWord.Dispose();
// 打包为 ZIP 下载
const JSZip = require('jszip');
const zip = new JSZip();
let items = window.dotnetRuntime.Module.FS.readdir(outputDir);
items = items.filter(item => item !== '.' && item !== '..');
for (const item of items) {
const fileData = window.dotnetRuntime.Module.FS.readFile(outputDir + item);
zip.file(item, fileData);
}
const zipBlob = await zip.generateAsync({ type: 'blob' });
const url = URL.createObjectURL(zipBlob);
const a = document.createElement('a');
a.href = url;
a.download = 'SplitByPageBreak.zip';
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Split Word Document By Page Break</h1>
<button onClick={splitByPageBreak}>Generate</button>
</div>
);
}
export default App;
按分页符拆分后生成的 Word 文档

常见问题
拆分后的文档格式与原文档不一致
原因:按分页符拆分时,仅克隆了段落内容,未同步克隆原文档的样式、主题和节属性,导致拆分后的文档丢失字体、颜色、页面设置等格式信息。
解决:创建新文档后,使用以下方法克隆原文档的样式和主题:
original.CloneDefaultStyleTo(newWord);
original.CloneThemesTo(newWord);
original.CloneCompatibilityTo(newWord);
sec.CloneSectionPropertiesTo(section);
分页符检测不到
原因:分页符位于段落子对象中,通过 BreakType 枚举判断。若遍历层级不正确,或未使用 instanceof 判断对象类型,会导致无法正确识别分页符。
解决:确保按 Paragraph.ChildObjects → instanceof Break → BreakType == BreakType.PageBreak 的顺序检测:
for (let k = 0; k < para.ChildObjects.Count; k++) {
let parobj = para.ChildObjects.get_Item(k);
if (parobj instanceof docModule.Break &&
parobj.BreakType === docModule.BreakType.PageBreak) {
// 找到分页符
}
}
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







