样式是 Word 里复用格式的方式:把一套格式(字体、字号、颜色、段落间距……)命名保存下来,之后任何段落只要挂上这个样式名,就自动获得这一整套格式。改样式定义,所有引用它的段落同步更新——这正是「直接给段落设格式」做不到的。
结构上,一个段落样式同时持有字符格式和段落格式两部分。取用内置样式后,通过 ParagraphStyle.CharacterFormat 改文字层面的属性,通过 ParagraphStyle.ParagraphFormat 改段落层面的属性。Spire.Doc for JavaScript 把这套模型完整映射到 Document.Styles 集合上。
本文介绍两个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.Doc for JavaScript 的方法。以下示例默认已安装 Spire.Doc 并完成 WebAssembly 模块初始化。
取用并修改内置样式
Word 内置了 Title、Normal、Heading 1~9 等一批样式。document.AddStyle({ builtinStyle }) 会取出(若尚不存在则创建)指定的内置样式并返回它的对象,拿到之后就可以改写。
需要注意 AddStyle 的返回类型是通用的 Style,改写段落格式前要先确认它确实是段落样式——用 instanceof wasmModule.ParagraphStyle 判断即可。Normal 作为正文基准样式,改它会连带影响所有继承自它的样式,通常只用来统一正文字体与字号。
function App() {
const Styles = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
await window.spire.FetchFileToVFS("msyh.ttc", "/Library/Fonts/", `${process.env.PUBLIC_URL}static/font/`);
await window.spire.FetchFileToVFS("msyhbd.ttc", "/Library/Fonts/", `${process.env.PUBLIC_URL}static/font/`);
// 创建文档与节
let doc = new docModule.Document();
let sec = doc.AddSection();
// 取用内置「标题」样式并改写为自定义配色:下边框 + 左对齐
let titleStyle = doc.AddStyle({ builtinStyle: docModule.BuiltinStyle.Title });
// 判断是否为段落样式,是则同时设置段落格式
if (titleStyle instanceof docModule.ParagraphStyle) {
let ps = titleStyle;
ps.CharacterFormat.FontName = "微软雅黑";
ps.CharacterFormat.FontSize = 28;
ps.CharacterFormat.TextColor = docModule.Color.FromArgb(42, 123, 136);
ps.ParagraphFormat.Borders.Bottom.BorderType = docModule.BorderStyle.Single;
ps.ParagraphFormat.Borders.Bottom.Color = docModule.Color.FromArgb(42, 123, 136);
ps.ParagraphFormat.Borders.Bottom.LineWidth = 1.5;
ps.ParagraphFormat.HorizontalAlignment = docModule.HorizontalAlignment.Left;
}
// 正文样式:统一正文字体与字号
let normalStyle = doc.AddStyle({ builtinStyle: docModule.BuiltinStyle.Normal });
normalStyle.CharacterFormat.FontName = "微软雅黑";
normalStyle.CharacterFormat.FontSize = 11;
// 一级标题样式
let heading1Style = doc.AddStyle({ builtinStyle: docModule.BuiltinStyle.Heading1 });
heading1Style.CharacterFormat.FontName = "微软雅黑";
heading1Style.CharacterFormat.FontSize = 14;
heading1Style.CharacterFormat.Bold = true;
heading1Style.CharacterFormat.TextColor = docModule.Color.FromArgb(42, 123, 136);
// 二级标题样式
let heading2Style = doc.AddStyle({ builtinStyle: docModule.BuiltinStyle.Heading2 });
heading2Style.CharacterFormat.FontName = "微软雅黑";
heading2Style.CharacterFormat.FontSize = 12;
heading2Style.CharacterFormat.Bold = true;
// 自定义项目符号列表样式
let bulletList = doc.Styles.Add({ listType: docModule.ListType.Bulleted, name: "bulletList" });
doc.Styles.Add({ style: bulletList });
// 应用样式:内置样式用 builtinStyle,自定义样式用名称
let paragraph = sec.AddParagraph();
paragraph.AppendText("季度运营报告");
paragraph.ApplyStyle({ builtinStyle: docModule.BuiltinStyle.Title });
paragraph = sec.AddParagraph();
paragraph.AppendText("编制部门:运营管理部 | 编制日期:2026 年 9 月");
paragraph.ApplyStyle({ builtinStyle: docModule.BuiltinStyle.Normal });
paragraph = sec.AddParagraph();
paragraph.AppendText("总体进展");
paragraph.ApplyStyle({ builtinStyle: docModule.BuiltinStyle.Heading1 });
paragraph = sec.AddParagraph();
paragraph.AppendText("本季度三条产品线均按计划推进,整体交付节奏平稳。");
paragraph.ApplyStyle({ builtinStyle: docModule.BuiltinStyle.Normal });
paragraph = sec.AddParagraph();
paragraph.AppendText("重点事项");
paragraph.ApplyStyle({ builtinStyle: docModule.BuiltinStyle.Heading1 });
paragraph = sec.AddParagraph();
paragraph.AppendText("关键里程碑");
paragraph.ApplyStyle({ builtinStyle: docModule.BuiltinStyle.Heading2 });
paragraph = sec.AddParagraph();
paragraph.AppendText("核心模块完成联调");
paragraph.ListFormat.ApplyStyle("bulletList");
paragraph = sec.AddParagraph();
paragraph.AppendText("试运行阶段启动");
paragraph.ListFormat.ApplyStyle("bulletList");
paragraph = sec.AddParagraph();
paragraph.AppendText("上线前评审排期");
paragraph.ListFormat.ApplyStyle("bulletList");
paragraph = sec.AddParagraph();
paragraph.AppendText("资源投入");
paragraph.ApplyStyle({ builtinStyle: docModule.BuiltinStyle.Heading2 });
paragraph = sec.AddParagraph();
paragraph.AppendText("当前团队人力较为紧张,建议在季度初完成排期确认。");
paragraph.ListFormat.ApplyStyle("bulletList");
// 定义输出文件名
const outputFileName = "Styles-result.docx";
// 保存文档到指定路径
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
doc.Dispose();
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>创建样式并应用到段落</h1>
<button onClick={Styles}>开始</button>
</div>
);
}
export default App;
内置的 Title、Heading 1、Heading 2 被改写成统一的青色配色,自定义的 bulletList 则提供项目符号

在文档之间复制样式
企业里常有一份「样式母版」文档,新文档需要沿用它的样式。逐个手动重建样式既慢又容易漏,直接遍历源文档的 Styles 集合、把每个样式对象加入目标文档即可。
document.Styles 支持 Count 与 get_Item(index),因此可以按索引完整遍历。源文档的样式覆盖目标文档后,目标文档里原本引用这些样式名的段落就会立刻呈现出源文档的格式。
本例使用两个示例文档:CopyDocumentStyles1.docx 是带自定义样式的源文档,CopyDocumentStyles2.docx 是目标文档——它的部分段落引用了源文档才有的样式名,但自身并未定义,因此复制前这些段落按默认格式显示。
function App() {
const CopyDocumentStyles = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 将两个示例文件载入虚拟文件系统(VFS)
let inputFileName_1 = "CopyDocumentStyles1.docx";
await window.spire.FetchFileToVFS(inputFileName_1, "", `${process.env.PUBLIC_URL}static/data/`);
let inputFileName_2 = "CopyDocumentStyles2.docx";
await window.spire.FetchFileToVFS(inputFileName_2, "", `${process.env.PUBLIC_URL}static/data/`);
// 加载源文档(带自定义样式)
let srcDoc = new docModule.Document();
srcDoc.LoadFromFile(inputFileName_1);
// 加载目标文档(只有内置样式)
let destDoc = new docModule.Document();
destDoc.LoadFromFile(inputFileName_2);
// 取源文档的样式集合
let styles = srcDoc.Styles;
// 逐个加入目标文档
for (let i = 0; i < styles.Count; i++) {
let style = styles.get_Item(i);
destDoc.Styles.Add(style);
}
// 定义输出文件名
const outputFileName = "CopyDocumentStyles_result.docx";
// 保存文档到指定路径
destDoc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
destDoc.Dispose();
srcDoc.Dispose();
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>将源文档的样式复制到目标文档</h1>
<button onClick={CopyDocumentStyles}>开始</button>
</div>
);
}
export default App;
复制后目标文档获得了源文档的自定义样式,原本「引用了样式却不带格式」的段落恢复正常显示

常见问题
修改了 Normal 样式,但正文段落没有全部跟着变
原因:只有继承自 Normal 的样式才会受其影响。如果段落自带了直接格式(例如逐段设置了 CharacterFormat.FontName),直接格式的优先级高于样式,会盖住样式的设定。
解决:统一改用样式控制外观,去掉段落与 run 上的直接格式设置。Normal 常用来统一正文字体与字号:
let normalStyle = document.AddStyle({ builtinStyle: wasmModule.BuiltinStyle.Normal });
normalStyle.CharacterFormat.FontName = "微软雅黑";
normalStyle.CharacterFormat.FontSize = 11;
复制后目标文档的样式数量翻了一倍
原因:遍历时把源文档的全部样式都复制了过去,其中包含大量内置样式。这些样式名在目标文档里往往已经存在,逐个 Add 会形成重复条目。
解决:这就是该示例的实际行为(样式集合会明显膨胀)。实际项目中如果只需要自定义样式,建议先按名称过滤,只复制目标文档中尚不存在的样式:
for (let i = 0; i < srcDoc.Styles.Count; i++) {
let style = srcDoc.Styles.get_Item(i);
// 检查目标文档里是否已有同名样式
let exists = false;
for (let j = 0; j < destDoc.Styles.Count; j++) {
if (destDoc.Styles.get_Item(j).Name === style.Name) {
exists = true;
break;
}
}
// 只补充目标文档缺失的样式
if (!exists) {
destDoc.Styles.Add(style);
}
}
自定义样式应用到段落时不生效
原因:ApplyStyle 对内置样式和自定义样式的调用方式不同——内置样式传 { builtinStyle } 对象,自定义样式传样式名字符串。传错形式时会静默忽略。
解决:按样式来源选择对应的调用形式:
// 内置样式
paragraph.ApplyStyle({ builtinStyle: wasmModule.BuiltinStyle.Heading1 });
// 自定义样式(字符串名,需与 Add 时的 name 一致)
paragraph.ListFormat.ApplyStyle("bulletList");
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







