上一类需求里,列表只要编号连续就够了;但实际文档中经常需要「另起一组,从指定数字开始」,或者把默认的圆点换成更醒目的符号。这两件事改的都不是段落,而是列表样式本身的层级参数——它们都挂在 ListRef.Levels 上,只是分别对应不同的属性:起始编号用 StartAt,符号字形用 BulletCharacter。Spire.Doc for JavaScript 让这些参数能在浏览器端直接读写。
本文介绍两个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.Doc for JavaScript 的方法。以下示例默认已安装 Spire.Doc 并完成 WebAssembly 模块初始化。
让列表从指定编号重新开始
如果两组列表共用同一个样式对象,Word 会把它们视为同一份编号序列,第二组会接着第一组的数字往下排。要让第二组重新计数,最直接的做法是为它单独建一个列表样式,并设置该样式第 0 级的 StartAt 属性——它决定这一级从哪个数字开始。
StartAt 的下标语义与 ListLevelNumber 一致:get_Item(0) 即第一级。示例中第二个列表设为 10,因此它的第一条显示为 10.:
function App() {
const RestartList = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 创建文档与节
let doc = new docModule.Document();
let section = doc.AddSection();
// 分组小标题
let paragraph = section.AddParagraph();
paragraph.AppendText("第一组列表");
// 第一个列表样式:默认从 1 开始
let numberList = doc.Styles.Add({ listType: docModule.ListType.Numbered, name: "Numbered1" });
doc.Styles.Add(numberList);
// 逐段应用样式
paragraph = section.AddParagraph();
paragraph.AppendText("事项一");
paragraph.ListFormat.ApplyStyle(numberList.Name);
paragraph = section.AddParagraph();
paragraph.AppendText("事项二");
paragraph.ListFormat.ApplyStyle(numberList.Name);
paragraph = section.AddParagraph();
paragraph.AppendText("事项三");
paragraph.ListFormat.ApplyStyle(numberList.Name);
paragraph = section.AddParagraph();
paragraph.AppendText("事项四");
paragraph.ListFormat.ApplyStyle(numberList.Name);
// 分组小标题
paragraph = section.AddParagraph();
paragraph.AppendText("第二组列表");
// 第二个列表样式:把第 0 级的起始编号设为 10
let numberList2 = doc.Styles.Add({ listType: docModule.ListType.Numbered, name: "Numbered2" });
numberList2.ListRef.Levels.get_Item(0).StartAt = 10;
doc.Styles.Add(numberList2);
// 逐段应用第二个样式,编号从 10 开始
paragraph = section.AddParagraph();
paragraph.AppendText("事项五");
paragraph.ListFormat.ApplyStyle(numberList2.Name);
paragraph = section.AddParagraph();
paragraph.AppendText("事项六");
paragraph.ListFormat.ApplyStyle(numberList2.Name);
paragraph = section.AddParagraph();
paragraph.AppendText("事项七");
paragraph.ListFormat.ApplyStyle(numberList2.Name);
paragraph = section.AddParagraph();
paragraph.AppendText("事项八");
paragraph.ListFormat.ApplyStyle(numberList2.Name);
// 定义输出文件名
const outputFileName = "RestartList-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={RestartList}>开始</button>
</div>
);
}
export default App;
第一组列表编号为 1~4,第二组从 10 开始,编号为 10~13

自定义项目符号的显示字形
项目符号列表默认使用 · 之类的圆点。要换成别的形状,需要改两个属性:
BulletCharacter—— 符号本身,它是一个字符,可以用String.fromCharCode()按 ASCII/Unicode 码位生成;CharacterFormat.FontName—— 承载该字符的字体。符号形状其实是由字体决定的,同一码位在不同字体下是不同图形。
关键在于第二点:Wingdings 这类符号字体把普通字母映射成了几何图形,因此同一个字符码在 Wingdings 下会呈现出与常规字体完全不同的样子。下面的示例用四个不同码位建了四个列表样式,每个样式套用同一段文字,便于横向比较符号差异:
function App() {
const ASCIICharactersBulletStyle = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 创建文档与节
let doc = new docModule.Document();
let section = doc.AddSection();
// 用 ASCII 码指定符号,并指定承载符号的字体为 Wingdings
let listStyle1 = doc.Styles.Add({ listType: docModule.ListType.Bulleted, name: "liststyle" });
listStyle1.ListRef.Levels.get_Item(0).BulletCharacter = String.fromCharCode(0x006e);
listStyle1.ListRef.Levels.get_Item(0).CharacterFormat.FontName = "Wingdings";
let listStyle2 = doc.Styles.Add({ listType: docModule.ListType.Bulleted, name: "liststyle2" });
listStyle2.ListRef.Levels.get_Item(0).BulletCharacter = String.fromCharCode(0x0075);
listStyle2.ListRef.Levels.get_Item(0).CharacterFormat.FontName = "Wingdings";
let listStyle3 = doc.Styles.Add({ listType: docModule.ListType.Bulleted, name: "liststyle3" });
listStyle3.ListRef.Levels.get_Item(0).BulletCharacter = String.fromCharCode(0x00b2);
listStyle3.ListRef.Levels.get_Item(0).CharacterFormat.FontName = "Wingdings";
let listStyle4 = doc.Styles.Add({ listType: docModule.ListType.Bulleted, name: "liststyle4" });
listStyle4.ListRef.Levels.get_Item(0).BulletCharacter = String.fromCharCode(0x00d8);
listStyle4.ListRef.Levels.get_Item(0).CharacterFormat.FontName = "Wingdings";
// 四个段落使用同一段文字,分别套用四种列表样式
let p1 = section.Body.AddParagraph();
p1.AppendText("同一段文字,四种项目符号");
p1.ListFormat.ApplyStyle(listStyle1.Name);
let p2 = section.Body.AddParagraph();
p2.AppendText("同一段文字,四种项目符号");
p2.ListFormat.ApplyStyle(listStyle2.Name);
let p3 = section.Body.AddParagraph();
p3.AppendText("同一段文字,四种项目符号");
p3.ListFormat.ApplyStyle(listStyle3.Name);
let p4 = section.Body.AddParagraph();
p4.AppendText("同一段文字,四种项目符号");
p4.ListFormat.ApplyStyle(listStyle4.Name);
// 定义输出文件名
const outputFileName = "ASCIICharactersBulletStyle-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>使用 ASCII 字符创建项目符号样式</h1>
<button onClick={ASCIICharactersBulletStyle}>开始</button>
</div>
);
}
export default App;
四行相同的文字配上了四种不同的项目符号,差异来自 BulletCharacter 码位

常见问题
设置了 StartAt,但列表仍接着上一组继续编号
原因:新旧两组列表复用了同一个样式对象。同一个样式的所有引用共享同一份编号序列,改 StartAt 等于把整条序列的起点都改掉。
解决:为需要重新计数的那一组单独 Add 一个新样式,并在新样式上设置 StartAt:
let numberList2 = document.Styles.Add({ listType: wasmModule.ListType.Numbered, name: "Numbered2" });
numberList2.ListRef.Levels.get_Item(0).StartAt = 10;
自定义的项目符号显示成了方框或乱码
原因:只设了 BulletCharacter 却没设字体,或设成了不含该字形的常规字体,系统无法渲染对应码位,就会退化成缺字方块。
解决:把符号字体设为确实包含该字形的符号字体(如 Wingdings):
listStyle1.ListRef.Levels.get_Item(0).BulletCharacter = String.fromCharCode(0x006e);
listStyle1.ListRef.Levels.get_Item(0).CharacterFormat.FontName = "Wingdings";
列表层级参数改了却没有生效
原因:ListRef.Levels 的下标从 0 开始,若按日常习惯从 1 开始写,改到的其实是第二级,第一级纹丝不动。
解决:确认下标——get_Item(0) 是第一级:
// 第一级
numberList.ListRef.Levels.get_Item(0).StartAt = 10;
// 第二级
numberList.ListRef.Levels.get_Item(1).NumberPrefix = "%1.";
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。









