SmartArt 图形把流程、层级与循环关系压缩成直观的版面,但其中的文字只能逐个点开查看或复制。需要把节点内容整理成清单、导入其他系统或做全文检索时,手工摘录既费时又容易遗漏;图形里过时的环节和冗余节点,也只能在界面上逐个删除。
本文使用 Spire.Presentation for JavaScript 在浏览器中提取 PowerPoint SmartArt 图形的文本并保存为文本文件,同时删除图形中不需要的节点。整个处理过程基于 WebAssembly 在用户设备本地完成,无需安装 Office,也不依赖后端服务,演示文稿不必离开浏览器。
本文介绍两个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.Presentation for JavaScript。以下示例默认 Spire.Presentation for JavaScript 已安装、WebAssembly 模块已初始化。
提取演示文稿中所有 SmartArt 图形的文本
一份演示文稿往往不止一个图形,逐页打开复制效率很低。把整份文件中的 SmartArt 文字一次汇总到同一个文本文件中,既能快速浏览全部内容,也方便统一检索与归档。
| 写法 | 得到的结果 |
|---|---|
ppt.Slides.Count |
演示文稿中的幻灯片总数 |
shape instanceof pptModule.ISmartArt |
判断形状是否为 SmartArt 图形 |
shape.Nodes.Count |
图形中的节点数量 |
shape.Nodes.get_Item(i).TextFrame.Text |
读取索引 i 对应节点的文字 |
window.dotnetRuntime.Module.FS.writeFile(fileName, text) |
把字符串写入 VFS 中的文本文件 |
具体操作步骤如下:
- 获取 Spire.Presentation 的 WASM 模块并确认已就绪,将字体文件与演示文稿载入 VFS。
- 创建
Presentation对象并调用LoadFromFile()加载演示文稿。 - 按
Slides.Count逐张遍历幻灯片,对每页的Shapes判断是否为ISmartArt。 - 每找到一个图形,先写入一条来源标题,再按
Nodes.Count遍历节点,用TextFrame.Text读取文字并写入列表。 - 把汇总行用
\r\n连接,调用window.dotnetRuntime.Module.FS.writeFile()写入.txt文件。 - 从 VFS 读出文本文件并触发下载,并用
Dispose()释放演示文稿。
提取演示文稿中所有 SmartArt 图形的文本的代码如下:
function App() {
const extractAllSmartArt = async () => {
// 获取 Spire.Presentation WASM 模块
const pptModule = window.wasmModule?.spirepresentation;
// 检查模块是否就绪
if (!pptModule) {
alert('Spire.Presentation is not ready yet');
return;
}
// 将字体与演示文稿载入 VFS
await window.spire.FetchFileToVFS('simsun.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'SmartArt.pptx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// 加载演示文稿
const ppt = new pptModule.Presentation();
ppt.LoadFromFile(inputFileName);
// 逐张幻灯片、逐个形状收集 SmartArt 文本
const lines = [];
for (let s = 0; s < ppt.Slides.Count; s++) {
const slide = ppt.Slides.get_Item(s);
let graphicNo = 0;
for (let i = 0; i < slide.Shapes.Count; i++) {
const shape = slide.Shapes.get_Item(i);
if (!(shape instanceof pptModule.ISmartArt)) continue;
graphicNo++;
lines.push(`第 ${s + 1} 张幻灯片 · SmartArt ${graphicNo}`);
for (let k = 0; k < shape.Nodes.Count; k++) {
lines.push(shape.Nodes.get_Item(k).TextFrame.Text);
}
}
}
// 将汇总结果写入文本文件
const outputFileName = 'ExtractAllSmartArtText.txt';
window.dotnetRuntime.Module.FS.writeFile(outputFileName, lines.join('\r\n'));
// 从 VFS 读取生成的文本文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
ppt.Dispose();
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>汇总全部 SmartArt 文本</h1>
<button onClick={extractAllSmartArt}>
汇总全部文本
</button>
</div>
);
}
export default App;
提取演示文稿中所有 SmartArt 图形的文本后的文本文件:

删除 SmartArt 图形中的节点
图形里的占位环节与过时步骤会让版面显得冗余。组织架构图按层级组织内容,删除节点时也要指明节点所在的层级:可以从某个节点的子节点集合中移除下属节点,也可以直接删除最上层的节点。图形按剩余节点重新排布,其余节点的文字保持不变;修改结果另存为新文件,原演示文稿不受影响。
| 写法 | 得到的结果 |
|---|---|
smartArt.Nodes.get_Item(0) |
取得图形最上层的节点 |
node.ChildNodes.RemoveNodeByPosition(position) |
删除该节点下指定位置的子节点,后续子节点顺次前移 |
smartArt.Nodes.RemoveNodeByPosition(position) |
删除指定位置的顶层节点,其余节点重新排布 |
ppt.SaveToFile({ file, fileFormat }) |
把修改后的演示文稿保存到 VFS 文件 |
具体操作步骤如下:
- 获取 Spire.Presentation 的 WASM 模块并确认已就绪,将字体文件与演示文稿载入 VFS。
- 创建
Presentation对象并调用LoadFromFile()加载演示文稿,用Slides.get_Item()取得包含组织架构图的幻灯片,再遍历Shapes找到 SmartArt 图形。 - 用
Nodes.get_Item(0)取得最上层的根节点,调用其ChildNodes.RemoveNodeByPosition()删除指定位置的子节点,位置从0开始计数。 - 调用
Nodes.RemoveNodeByPosition()删除根节点本身,剩余节点重新排布。 - 调用
Presentation.SaveToFile()把修改后的演示文稿保存为新的.pptx文件。 - 从 VFS 读出结果文件并触发下载,最后用
Dispose()释放演示文稿。
删除 SmartArt 图形中的节点的代码如下:
function App() {
const removeSmartArtNode = async () => {
// 获取 Spire.Presentation WASM 模块
const pptModule = window.wasmModule?.spirepresentation;
// 检查模块是否就绪
if (!pptModule) {
alert('Spire.Presentation is not ready yet');
return;
}
// 将字体与演示文稿载入 VFS
await window.spire.FetchFileToVFS('simsun.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'SmartArt.pptx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// 加载演示文稿并取得包含组织架构图的第二张幻灯片
const ppt = new pptModule.Presentation();
ppt.LoadFromFile(inputFileName);
const slide = ppt.Slides.get_Item(1);
// 在幻灯片中查找 SmartArt 图形
let smartArt = null;
for (let i = 0; i < slide.Shapes.Count; i++) {
const shape = slide.Shapes.get_Item(i);
if (shape instanceof pptModule.ISmartArt) {
smartArt = shape;
break;
}
}
// 取得最上层的根节点
const root = smartArt.Nodes.get_Item(0);
// 删除根节点下位置为 1 的子节点(位置从 0 开始计数)
root.ChildNodes.RemoveNodeByPosition(1);
// 删除根节点本身
smartArt.Nodes.RemoveNodeByPosition(0);
// 保存结果文件
const outputFileName = 'RemoveSmartArtNode.pptx';
ppt.SaveToFile({ file: outputFileName, fileFormat: pptModule.FileFormat.Pptx2013 });
// 从 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);
ppt.Dispose();
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>删除 SmartArt 节点</h1>
<button onClick={removeSmartArtNode}>
删除节点
</button>
</div>
);
}
export default App;
删除 SmartArt 图形中的节点后的演示文稿:

常见问题
多层级的 SmartArt 子节点文字怎么读取
原因:各级节点都记录在 Nodes 集合中;ChildNodes 只返回某个节点的直接子节点,两个集合的用途不同。
解决:需要全部节点文字时遍历 Nodes;只需要某个节点下属的文字时,读取该节点的 ChildNodes:
for (let i = 0; i < smartArt.Nodes.Count; i++) {
lines.push(smartArt.Nodes.get_Item(i).TextFrame.Text);
}
// 只读取第一个节点的直接子节点
const firstNode = smartArt.Nodes.get_Item(0);
for (let i = 0; i < firstNode.ChildNodes.Count; i++) {
lines.push(firstNode.ChildNodes.get_Item(i).TextFrame.Text);
}
一次删除多个节点为什么会删错或漏删
原因:每删除一个节点,后面的节点会依次前移,位置与索引随之重新编号;按删除前记下的位置继续操作,就会落到别的节点上。
解决:倒序遍历节点集合后再删除:
for (let i = smartArt.Nodes.Count - 1; i >= 0; i--) {
const node = smartArt.Nodes.get_Item(i);
if (node.TextFrame.Text === '目标文字') {
smartArt.Nodes.RemoveNode({ index: i });
}
}
删除组织架构图的根节点会连带删除子节点吗
原因:RemoveNodeByPosition() 一次只删除指定位置上的一个节点,不会级联删除它的子节点。
解决:删除根节点时只调用一次 RemoveNodeByPosition(0):
smartArt.Nodes.RemoveNodeByPosition(0);
删除后,原来的子节点仍然保留,其中一个子节点会升为 Level 0,其余子节点保持 Level 1,位置重新编号。如果目的是清空整个图形,可以直接删除 SmartArt 形状(slide.Shapes.Remove(shape))。
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







