演示文稿的页数一多,翻找和讲述都变得费劲:哪几页属于开场、哪几页是附录,只能靠记忆。PowerPoint 的节把这些页分组,左侧缩略图按节折叠,放映、复制和交接都省事。桌面端可以右键逐页建节,但面对批量文件或需要接进 Web 流程时,逐份手工操作并不现实。
本文用 Spire.Presentation for JavaScript 在浏览器中增删 PowerPoint 节。它基于 WebAssembly 在浏览器端运行,无需安装 Office,不依赖后端,文件通过虚拟文件系统(VFS)在本地读写。
本文介绍四个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.Presentation for JavaScript。下面的示例假定 Spire.Presentation 已安装、WebAssembly 模块已初始化。
在 PowerPoint 文档的末尾新增节
SectionList.Append() 用于在节列表末尾追加一个节,参数是节名。新节默认不含幻灯片,在 PowerPoint 的节窗格里以一条独立的节标题出现。这个空节不影响原有分组的页码与归属。
具体操作步骤如下:
- 获取 Spire.Presentation 的 WASM 模块,确认已就绪。
- 读入示例演示文稿与字体,创建
Presentation对象并加载该文件。 - 使用
Presentation.SectionList.Append()方法在末尾新增节。 - 使用
Presentation.SaveToFile()方法保存结果文件。 - 从 VFS 读出结果文件并触发浏览器下载。
在末尾新增节的代码如下:
function App() {
const appendSection = async () => {
// 获取 Spire.Presentation WASM 模块
const pptModule = window.wasmModule?.spirepresentation;
// 检查模块是否就绪
if (!pptModule) {
alert('Spire.Presentation is not ready yet');
return;
}
// 载入示例演示文稿与字体
await window.spire.FetchFileToVFS('含节的演示文稿.pptx', "", `${process.env.PUBLIC_URL}/data/`);
await window.spire.FetchFileToVFS('ARIALUNI.TTF', "/Library/Fonts/", `${process.env.PUBLIC_URL}/font/`);
// 创建 Presentation 实例并加载演示文稿
const ppt = new pptModule.Presentation();
ppt.LoadFromFile('含节的演示文稿.pptx');
// 在节列表末尾新增「附录」节
ppt.SectionList.Append('附录');
// 保存结果文件
const outputFileName = '末尾新增节后.pptx';
ppt.SaveToFile({ file: outputFileName, fileFormat: pptModule.FileFormat.Pptx2013 });
ppt.Dispose();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation' });
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={appendSection}>
新增节
</button>
</div>
);
}
export default App;
节列表末尾多出一个「附录」节:

在 PowerPoint 文档特定节前新增节
SectionList.Insert() 用于在指定位置插入节。第一个参数是节的索引,从 0 起算。新节插在该索引之前,原来的节依次后移。
具体操作步骤如下:
- 获取 Spire.Presentation 的 WASM 模块,确认已就绪。
- 读入示例演示文稿与字体,创建
Presentation对象并加载该文件。 - 使用
Presentation.SectionList.Insert()方法在「数据分析」节前插入新节。 - 使用
Presentation.SaveToFile()方法保存结果文件。 - 从 VFS 读出结果文件并触发浏览器下载。
在特定节前新增节的代码如下:
function App() {
const insertSectionBeforeSection = async () => {
// 获取 Spire.Presentation WASM 模块
const pptModule = window.wasmModule?.spirepresentation;
// 检查模块是否就绪
if (!pptModule) {
alert('Spire.Presentation is not ready yet');
return;
}
// 载入示例演示文稿与字体
await window.spire.FetchFileToVFS('含节的演示文稿.pptx', "", `${process.env.PUBLIC_URL}/data/`);
await window.spire.FetchFileToVFS('ARIALUNI.TTF', "/Library/Fonts/", `${process.env.PUBLIC_URL}/font/`);
// 创建 Presentation 实例并加载演示文稿
const ppt = new pptModule.Presentation();
ppt.LoadFromFile('含节的演示文稿.pptx');
// 在索引 1 处插入新节,即插在「数据分析」节之前
ppt.SectionList.Insert(1, '产品规划');
// 保存结果文件
const outputFileName = '节前新增节后.pptx';
ppt.SaveToFile({ file: outputFileName, fileFormat: pptModule.FileFormat.Pptx2013 });
ppt.Dispose();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation' });
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={insertSectionBeforeSection}>
新增节
</button>
</div>
);
}
export default App;
「数据分析」节前插入了「产品规划」节:

在 PowerPoint 文档特定幻灯片前新增节
手上只有幻灯片、不记得它属于第几节时,SectionList.Add() 带幻灯片参数的重载可以直接解决:把目标页传进去,节边界就落在这一页之前,该页及它在原节里其后的页面自动归入新节。幻灯片本身不增不减,内容与顺序都保持不变。
具体操作步骤如下:
- 获取 Spire.Presentation 的 WASM 模块,确认已就绪。
- 读入示例演示文稿与字体,创建
Presentation对象并加载该文件。 - 使用
Presentation.SectionList.Add()以目标幻灯片为起点新增节。 - 使用
Presentation.SaveToFile()方法保存结果文件。 - 从 VFS 读出结果文件并触发浏览器下载。
在特定幻灯片前新增节的代码如下:
function App() {
const insertSectionBeforeSlide = async () => {
// 获取 Spire.Presentation WASM 模块
const pptModule = window.wasmModule?.spirepresentation;
// 检查模块是否就绪
if (!pptModule) {
alert('Spire.Presentation is not ready yet');
return;
}
// 载入示例演示文稿与字体
await window.spire.FetchFileToVFS('含节的演示文稿.pptx', "", `${process.env.PUBLIC_URL}/data/`);
await window.spire.FetchFileToVFS('ARIALUNI.TTF', "/Library/Fonts/", `${process.env.PUBLIC_URL}/font/`);
// 创建 Presentation 实例并加载演示文稿
const ppt = new pptModule.Presentation();
ppt.LoadFromFile('含节的演示文稿.pptx');
// 目标幻灯片:第 4 张(0 基索引 3)
// 以该页为起点新增「市场洞察」节,这一页之前形成新的节边界
ppt.SectionList.Add('市场洞察', ppt.Slides.get_Item(3));
// 保存结果文件
const outputFileName = '幻灯片前新增节后.pptx';
ppt.SaveToFile({ file: outputFileName, fileFormat: pptModule.FileFormat.Pptx2013 });
ppt.Dispose();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation' });
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={insertSectionBeforeSlide}>
新增节
</button>
</div>
);
}
export default App;
从第 4 张幻灯片起拆出「市场洞察」节,前面三页仍留在原来的节里:

从 PowerPoint 文档删除节
删除节用 SectionList.RemoveAt(),参数是节的位置索引;SectionList.RemoveAll() 则一次清空全部节,让演示文稿回到无节结构。删掉一个节不会删除其中的幻灯片,这些页会并入相邻的节,页码保持不变。
| 方法 | 作用 |
|---|---|
SectionList.RemoveAt(index) |
删除指定位置的节 |
SectionList.RemoveAll() |
删除全部节 |
具体操作步骤如下:
- 获取 Spire.Presentation 的 WASM 模块,确认已就绪。
- 读入示例演示文稿与字体,创建
Presentation对象并加载该文件。 - 使用
Presentation.SectionList.RemoveAt()方法删除「数据分析」节。 - 使用
Presentation.SaveToFile()方法保存结果文件。 - 从 VFS 读出结果文件并触发浏览器下载。
从演示文稿删除节的代码如下:
function App() {
const removeSection = async () => {
// 获取 Spire.Presentation WASM 模块
const pptModule = window.wasmModule?.spirepresentation;
// 检查模块是否就绪
if (!pptModule) {
alert('Spire.Presentation is not ready yet');
return;
}
// 载入示例演示文稿与字体
await window.spire.FetchFileToVFS('含节的演示文稿.pptx', "", `${process.env.PUBLIC_URL}/data/`);
await window.spire.FetchFileToVFS('ARIALUNI.TTF', "/Library/Fonts/", `${process.env.PUBLIC_URL}/font/`);
// 创建 Presentation 实例并加载演示文稿
const ppt = new pptModule.Presentation();
ppt.LoadFromFile('含节的演示文稿.pptx');
// 删除索引 1 处的「数据分析」节
ppt.SectionList.RemoveAt(1);
// 保存结果文件
const outputFileName = '删除节后.pptx';
ppt.SaveToFile({ file: outputFileName, fileFormat: pptModule.FileFormat.Pptx2013 });
ppt.Dispose();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation' });
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={removeSection}>
删除节
</button>
</div>
);
}
export default App;

上面的示例只删一个节。要一次清空全部节,改用 RemoveAll(),幻灯片页数不变:
// 删除第二个节
ppt.SectionList.RemoveAt(1)
// 删除所有的节
ppt.SectionList.RemoveAll()
常见问题
节索引从 0 开始还是从 1 开始
原因:SectionList.Insert() 和 SectionList.RemoveAt() 的索引都是 0 基,和 Slides 一致;PowerPoint 界面里显示的是第 1 节、第 2 节,两者相差 1。
解决:代码里按 0 基处理。要操作界面上看到的第 2 个节,传给方法的就是 1。拿不准时先遍历 SectionList.Count,按下标打印节名确认位置。
新增的节为什么没有幻灯片
原因:Append() 和 Insert() 只创建节的名称与分组边界,不会自动把幻灯片装进去。节是幻灯片的分组,新节初始可以为空,在节窗格里显示为一条没有缩略图的节标题。
解决:空节在保存和打开时都会保留,需要页面时在 PowerPoint 中把幻灯片拖到该节标题下即可。如果希望新节直接带上幻灯片,改用带幻灯片参数的重载 SectionList.Add(name, slide):传入的那一页会成为新节的第一页,新节的边界落在它之前,页面总数不变。
删除节会把幻灯片一起删掉吗
原因:节只是分组信息,删除节不会删除幻灯片本身。RemoveAt() 移除分组后,原来属于该节的页面会并入相邻的节,总页数不变。
解决:只想重新分组就删节,页面仍在。确实要去掉页面内容,得改用 Slides.RemoveAt() 或 Slides.Remove() 删除幻灯片。
一次可以删除多个节吗
原因:RemoveAt() 一次只删一个节,且每删一个,后面节的索引会前移一位。
解决:删多个节时从后往前删,或每次都删索引 0,避免索引错位。要清空全部节,直接用 RemoveAll():
// 清空全部节,幻灯片保留
ppt.SectionList.RemoveAll();
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







