同一套演示文稿反复套用,标题总要跟着项目、季度、汇报对象改。反过来,手上有一份几十页的稿子,想把每页标题汇成目录或清单,也只能逐页复制。放到服务端处理,文件上传后就不再留在用户的设备上。
本文用 Spire.Presentation for JavaScript 在浏览器里修改和提取幻灯片标题。ISlide.Title 直接读写指定页的标题占位符。需要一次收集整份文稿的标题时,则遍历每页的形状、按占位符类型筛选。整个过程基于 WebAssembly 在浏览器端完成,无需安装 Office,也不依赖后端。
本文介绍两个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.Presentation for JavaScript。下面的示例假定 Spire.Presentation 已安装、WebAssembly 模块已初始化。
修改 PowerPoint 幻灯片标题
Spire.Presentation for JavaScript 提供 ISlide.Title 属性,用于读写单张幻灯片的标题。赋值即替换标题占位符里的文字,占位符的位置与字号沿用原样。页面原来没有标题占位符时,赋值会补建一个。
Title 作用在标题占位符上,页面上其他形状不受影响:
| 占位符类型 | Title 是否作用于此 |
|---|---|
PlaceholderType.Title |
是 |
PlaceholderType.CenteredTitle |
是 |
PlaceholderType.Subtitle |
否 |
具体操作步骤如下:
- 获取 Spire.Presentation 的 WASM 模块,确认已就绪。
- 读入示例演示文稿与字体,创建
Presentation对象并加载该文件。 - 用
Presentation.Slides.get_Item()取出目标幻灯片,给ISlide.Title赋新标题。 - 使用
Presentation.SaveToFile()方法保存结果文件。 - 从 VFS 读出结果文件并触发浏览器下载。
修改 PowerPoint 幻灯片标题的代码如下:
function App() {
const modifyTitles = 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');
// 按索引取出幻灯片,给 Title 赋新标题
ppt.Slides.get_Item(0).Title = '2026 年度业务汇报';
ppt.Slides.get_Item(1).Title = '核心指标(修订版)';
ppt.Slides.get_Item(3).Title = '下一步行动';
// 保存结果文件
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>修改 PowerPoint 幻灯片标题</h1>
<button onClick={modifyTitles}>
修改标题
</button>
</div>
);
}
export default App;
修改的标题均已替换:

提取 PowerPoint 幻灯片标题
Spire.Presentation for JavaScript 还提供按占位符收集标题的方式:遍历每页的形状,筛出占位符类型为 Title、CenteredTitle、Subtitle 的形状,读取 TextFrame.Text。标题页的副标题会一并收进来,正文与普通文本框则被排除在外。
| 占位符类型 | 说明 |
|---|---|
PlaceholderType.Title |
内容页的标题 |
PlaceholderType.CenteredTitle |
标题页的居中主标题 |
PlaceholderType.Subtitle |
标题页的副标题 |
具体操作步骤如下:
- 获取 Spire.Presentation 的 WASM 模块,确认已就绪。
- 读入示例演示文稿与字体,创建
Presentation对象并加载该文件。 - 遍历
Presentation.Slides与每页的Shapes,用shape.IsPlaceholder与shape.Placeholder.Type筛选三类标题占位符。 - 把命中形状的
TextFrame.Text依次收进数组。 - 用
FS.writeFile()写入标题清单文本,并触发浏览器下载。
提取 PowerPoint 幻灯片标题的代码如下:
function App() {
const extractTitles = 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');
// 遍历每页的每个形状,按占位符类型收集标题
const titles = [];
for (let i = 0; i < ppt.Slides.Count; i++) {
const slide = ppt.Slides.get_Item(i);
for (let j = 0; j < slide.Shapes.Count; j++) {
const shape = slide.Shapes.get_Item(j);
if (!shape.IsPlaceholder) continue;
const type = shape.Placeholder.Type;
if (type === pptModule.PlaceholderType.Title ||
type === pptModule.PlaceholderType.CenteredTitle ||
type === pptModule.PlaceholderType.Subtitle) {
titles.push(shape.TextFrame.Text);
}
}
}
// 写入标题清单,一行一个标题
const outputFileName = '幻灯片标题.txt';
window.dotnetRuntime.Module.FS.writeFile(outputFileName, titles.join('\n'));
ppt.Dispose();
// 从 VFS 读取文本,触发浏览器下载
const txtArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const txtBlob = new Blob([txtArray], { type: 'text/plain' });
const txtUrl = URL.createObjectURL(txtBlob);
const txtLink = document.createElement('a');
txtLink.href = txtUrl;
txtLink.download = outputFileName;
txtLink.click();
URL.revokeObjectURL(txtUrl);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>提取 PowerPoint 幻灯片标题</h1>
<button onClick={extractTitles}>
提取标题
</button>
</div>
);
}
export default App;
提取出的标题清单,每行一条,副标题也在其中:

常见问题
标题和页面上的普通文本框有什么区别
原因:ISlide.Title 只认标题占位符(Title、CenteredTitle)。有些模板为了排版,把标题做成了普通文本框,这类形状没有占位符信息,Title 读不到也改不到。
解决:确认标题形状带占位符后再用 Title。拿不到时,按形状名或位置定位普通文本框,直接改它的 TextFrame.Text。
幻灯片没有标题占位符时,读取 Title 会得到什么
原因:读取 Title 取的是标题占位符里的文字。页面没有标题占位符时,返回的是幻灯片的默认页名(如 Slide 1),并不是页面上的正文。写入不受影响——对这样的页面赋值 Title,库会补建一个标题占位符,再把文字写进去。
解决:要判断某页有没有标题,遍历形状看 shape.IsPlaceholder 与 shape.Placeholder.Type,不要只看 Title 的返回值。
为什么提取结果里多了副标题
原因:筛选条件包含 PlaceholderType.Subtitle,标题页的副标题会跟主标题一起被收进来。
解决:只要每页主标题时,把 Subtitle 从条件里去掉:
if (type === pptModule.PlaceholderType.Title ||
type === pptModule.PlaceholderType.CenteredTitle) {
titles.push(shape.TextFrame.Text);
}
直接访问 shape.Placeholder.Type 为什么会报错
原因:文本框中也有 Placeholder 这个属性,但它的类型为 null。绑定的包装对象仍会返回一个真值,跳过判空后继续取 .Type,就会抛出 Arg_NullReferenceException。
解决:先用 shape.IsPlaceholder 过滤,再访问 shape.Placeholder.Type:
if (!shape.IsPlaceholder) continue;
const type = shape.Placeholder.Type;
修改标题后,原来的字号和位置会变吗
原因:Title 替换的是标题占位符里的文字,占位符本身的位置、尺寸与文字格式沿用原设置。
解决:页面原本就有标题占位符时,不需要再调格式。若占位符是由赋值补建的,则使用默认位置与默认字号,需要时再设置它的 Frame 与文字格式。
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







