SmartArt graphics condense processes, hierarchies and cycles into a clear visual layout, but the text inside them can only be read or copied node by node. Turning the node contents into a checklist, importing them into another system, or searching them as plain text is slow and easy to miss by hand; outdated steps and redundant nodes also have to be removed one at a time in the editor.
This article uses Spire.Presentation for JavaScript to extract the text of PowerPoint SmartArt graphics in the browser, save it as text files, and delete unwanted nodes from a graphic. The whole process runs locally on the user's device through WebAssembly, requires no Office installation and no back-end service, and the presentation never leaves the browser.
The article covers two feature points:
For installation and project configuration, see Integrating Spire.Presentation for JavaScript in a React Project. The examples below assume that Spire.Presentation for JavaScript is installed and the WebAssembly module has been initialized.
Extract Text from Every SmartArt Graphic in the Presentation
A presentation often contains more than one graphic, and opening each slide to copy text by hand is slow. Collecting the SmartArt text from the whole file into a single text file makes the content easy to review, search and archive.
| Code | Result |
|---|---|
ppt.Slides.Count |
The total number of slides in the presentation |
shape instanceof pptModule.ISmartArt |
Checks whether a shape is a SmartArt graphic |
shape.Nodes.Count |
The number of nodes in the graphic |
shape.Nodes.get_Item(i).TextFrame.Text |
The text of the node at index i |
window.dotnetRuntime.Module.FS.writeFile(fileName, text) |
Writes a string to a text file in the VFS |
The steps are:
- Get the Spire.Presentation WASM module and make sure it is ready, then load the font and the presentation into the VFS.
- Create a
Presentationobject and callLoadFromFile()to load the presentation. - Iterate the slides with
Slides.Count, and check every shape on each slide forISmartArt. - For each graphic found, write a source heading, then iterate its nodes with
Nodes.Countand read each text withTextFrame.Textinto the list. - Join the collected lines with
\r\nand callwindow.dotnetRuntime.Module.FS.writeFile()to write them to a.txtfile. - Read the text file from the VFS to start the download, and release the presentation with
Dispose().
The code to extract text from every SmartArt graphic in the presentation is as follows:
function App() {
const extractAllSmartArt = async () => {
// Get the Spire.Presentation WASM module
const pptModule = window.wasmModule?.spirepresentation;
// Check that the module is ready
if (!pptModule) {
alert('Spire.Presentation is not ready yet');
return;
}
// Load the font and the presentation into the VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'SmartArt.pptx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// Load the presentation
const ppt = new pptModule.Presentation();
ppt.LoadFromFile(inputFileName);
// Collect SmartArt text from every shape on every slide
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(`Slide ${s + 1} · SmartArt ${graphicNo}`);
for (let k = 0; k < shape.Nodes.Count; k++) {
lines.push(shape.Nodes.get_Item(k).TextFrame.Text);
}
}
}
// Write the summary to a text file
const outputFileName = 'ExtractAllSmartArtText.txt';
window.dotnetRuntime.Module.FS.writeFile(outputFileName, lines.join('\r\n'));
// Read the generated text file from the VFS and trigger the download
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>Summarize SmartArt Text</h1>
<button onClick={extractAllSmartArt}>
Summarize All
</button>
</div>
);
}
export default App;
Text file after extracting text from every SmartArt graphic in the presentation:

Delete Nodes from a SmartArt Graphic
Placeholder steps and outdated stages make a graphic look cluttered. An organization chart arranges content by level, so deleting a node also means naming the level it sits on: you can remove a subordinate node from a node's child node collection, or delete the top-level node outright. The graphic re-flows around the remaining nodes and the other node texts stay unchanged; the result is saved to a new file, so the original presentation stays intact.
| Code | Result |
|---|---|
smartArt.Nodes.get_Item(0) |
Gets the top-level node of the graphic |
node.ChildNodes.RemoveNodeByPosition(position) |
Removes the child node at the given position under that node; later children move forward |
smartArt.Nodes.RemoveNodeByPosition(position) |
Removes the top-level node at the given position; the remaining nodes re-flow |
ppt.SaveToFile({ file, fileFormat }) |
Saves the modified presentation to a file in the VFS |
The steps are:
- Get the Spire.Presentation WASM module and make sure it is ready, then load the font and the presentation into the VFS.
- Create a
Presentationobject, callLoadFromFile()to load the presentation, get the slide that holds the organization chart withSlides.get_Item(), and find the SmartArt graphic by iterating its shapes. - Get the top-level root node with
Nodes.get_Item(0)and callChildNodes.RemoveNodeByPosition()to remove the child at the given position, where positions start at0. - Call
Nodes.RemoveNodeByPosition()to remove the root node itself; the remaining nodes re-flow. - Call
Presentation.SaveToFile()to save the modified presentation as a new.pptxfile. - Read the result file from the VFS to start the download, and release the presentation with
Dispose().
The code to delete nodes from a SmartArt graphic is as follows:
function App() {
const removeSmartArtNode = async () => {
// Get the Spire.Presentation WASM module
const pptModule = window.wasmModule?.spirepresentation;
// Check that the module is ready
if (!pptModule) {
alert('Spire.Presentation is not ready yet');
return;
}
// Load the font and the presentation into the VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'SmartArt.pptx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// Load the presentation and get the second slide, which holds the organization chart
const ppt = new pptModule.Presentation();
ppt.LoadFromFile(inputFileName);
const slide = ppt.Slides.get_Item(1);
// Find the SmartArt graphic on the slide
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;
}
}
// Get the top-level root node
const root = smartArt.Nodes.get_Item(0);
// Remove the child node at position 1 under the root (positions start at 0)
root.ChildNodes.RemoveNodeByPosition(1);
// Remove the root node itself
smartArt.Nodes.RemoveNodeByPosition(0);
// Save the result file
const outputFileName = 'RemoveSmartArtNode.pptx';
ppt.SaveToFile({ file: outputFileName, fileFormat: pptModule.FileFormat.Pptx2013 });
// Read the generated file from the VFS and trigger the download
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>Delete SmartArt Node</h1>
<button onClick={removeSmartArtNode}>
Delete Node
</button>
</div>
);
}
export default App;
Presentation after deleting nodes from a SmartArt graphic:

FAQ
How to read child node text in a multi-level SmartArt graphic
Cause: Every node, including child nodes, is stored in the Nodes collection; ChildNodes returns only the direct children of a single node, so the two collections serve different purposes.
Solution: Iterate Nodes when every node text is needed; to read only the nodes under one specific node, read that node's ChildNodes:
for (let i = 0; i < smartArt.Nodes.Count; i++) {
lines.push(smartArt.Nodes.get_Item(i).TextFrame.Text);
}
// read only the direct child nodes of the first node
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);
}
Why are the wrong nodes removed when deleting several nodes at once
Cause: Each removal moves the following nodes forward and renumbers their positions and indexes; continuing with positions recorded before the deletion then hits different nodes.
Solution: Iterate the collection backwards before deleting:
for (let i = smartArt.Nodes.Count - 1; i >= 0; i--) {
const node = smartArt.Nodes.get_Item(i);
if (node.TextFrame.Text === 'target text') {
smartArt.Nodes.RemoveNode({ index: i });
}
}
Does deleting the root node of an organization chart also delete its child nodes
Cause: RemoveNodeByPosition() removes only the node at the given position; it does not cascade to child nodes.
Solution: Remove the root node with a single call:
smartArt.Nodes.RemoveNodeByPosition(0);
The child nodes remain, one child is promoted to Level 0, the others keep Level 1, and positions are renumbered. To clear the whole graphic, remove the SmartArt shape with slide.Shapes.Remove(shape).
Get a Free License
If you wish to delete the evaluation message from the resulting documents, or to get rid of function limitations, please contact sales to obtain a valid 30-day temporary license.
