Split PowerPoint Slides with JavaScript in React

2026-11-07 05:00:53 Written by  liu talia
Rate this item
(0 votes)

Once a presentation is finished, the way its pages are organized often changes with the situation: when sending materials out, each slide may need to stand alone; when preparing an excerpt, only a few consecutive pages are needed. Saving extra copies and copying slides by hand takes time and can easily lose charts, speaker notes, or layout details. Handling it on a server means the file must first be uploaded to a third-party environment.

This article uses Spire.Presentation for JavaScript to split PowerPoint slides in the browser. The whole process runs locally on the user's device through WebAssembly, requires no Office installation and no back-end service, and keeps the presentation from leaving the browser.

This article covers two core features:

For installation and project configuration, see Integrating Spire.Presentation for JavaScript in a React Project. The examples below assume that Spire.Presentation is installed and the WebAssembly module has been initialized.


Split a PowerPoint presentation into single slides

When distributing materials, each slide sometimes needs to stand alone so it can be sent, annotated, or used as image material separately. Splitting a presentation into multiple files means copying the content page by page and creating an independent presentation instance for each slide.

Code Result
new pptModule.Presentation() Creates a presentation instance with one blank slide by default
sourcePpt.Slides.Count Total number of slides in the source presentation
sourcePpt.Slides.get_Item(i) The (i+1)-th slide (index starts at 0)
singlePpt.Slides.RemoveAt(0) Removes the blank slide created with the new presentation
singlePpt.Slides.Append({ slide }) Copies the given slide to the end of the current presentation
singlePpt.SaveToFile({ file, fileFormat }) Writes a standalone PPTX file in the specified format

The steps are:

  1. Load the font file and the sample presentation Presentation.pptx into the VFS with window.spire.FetchFileToVFS, then create an instance with new pptModule.Presentation() and load the source file with LoadFromFile.
  2. Read sourcePpt.Slides.Count as the loop count and visit each source slide with sourcePpt.Slides.get_Item(i).
  3. In each iteration, create a new Presentation, call Slides.RemoveAt(0) to remove the default blank page, and copy the current slide with Slides.Append({ slide }).
  4. Save the new presentation as SplitSlide-<index>.pptx with SaveToFile, then release the instance with Dispose().
  5. Read every output file through window.dotnetRuntime.Module.FS.readFile, build a Blob, and trigger the browser download.
function App() {
  const splitIntoSlides = async () => {
    // Get the Spire.Presentation WASM module
    const pptModule = window.wasmModule?.spirepresentation;

    // Check if the module is ready
    if (!pptModule) {
      alert('Spire.Presentation is not ready yet');
      return;
    }

    // Load the font and the sample presentation into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'Presentation.pptx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Load the source presentation
    const sourcePpt = new pptModule.Presentation();
    sourcePpt.LoadFromFile(inputFileName);

    const splitFiles = [];

    // Split the slides one by one
    for (let i = 0; i < sourcePpt.Slides.Count; i++) {
      // Create a new presentation and remove its built-in blank slide
      const singlePpt = new pptModule.Presentation();
      singlePpt.Slides.RemoveAt(0);

      // Copy the i-th slide of the source presentation into the new one
      singlePpt.Slides.Append({ slide: sourcePpt.Slides.get_Item(i) });

      // Save it as a standalone PPTX file
      const outputFileName = `SplitSlide-${i + 1}.pptx`;
      singlePpt.SaveToFile({ file: outputFileName, fileFormat: pptModule.FileFormat.Pptx2013 });
      splitFiles.push(outputFileName);

      singlePpt.Dispose();
    }

    sourcePpt.Dispose();

    // Read the split results from the VFS and trigger the downloads
    for (const fileName of splitFiles) {
      const fileArray = window.dotnetRuntime.Module.FS.readFile(fileName);
      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 = fileName;
      a.click();
      URL.revokeObjectURL(url);
    }
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Split PowerPoint Slides</h1>
      <button onClick={splitIntoSlides}>
        Split into Single Slides
      </button>
    </div>
  );
}

export default App;

Presentation files after splitting into single slides:

Presentation files after splitting into single slides


Split PowerPoint slides by page range

Not every split needs one file per page. A report often only needs one section extracted, for example saving slides 2 to 4 as a separate brief. There is no need to copy the whole presentation and delete pages; determine the start and end indexes and append only the slides inside that range to a new presentation.

The steps are:

  1. Load the font and Presentation.pptx with window.spire.FetchFileToVFS, then create a Presentation instance and load the file with LoadFromFile.
  2. Create a new presentation with new pptModule.Presentation() and remove the default blank page with Slides.RemoveAt(0).
  3. Set startIndex and endIndex (indexes start at 0 and the range includes both ends), take each slide with Slides.get_Item(i) in a loop, and append it with Slides.Append({ slide }).
  4. Save the result as SplitRange.pptx with SaveToFile, and release both presentation instances with Dispose().
  5. Read the file through window.dotnetRuntime.Module.FS.readFile, build a Blob, and trigger the download.
function App() {
  const splitByRange = async () => {
    // Get the Spire.Presentation WASM module
    const pptModule = window.wasmModule?.spirepresentation;

    // Check if the module is ready
    if (!pptModule) {
      alert('Spire.Presentation is not ready yet');
      return;
    }

    // Load the font and the sample presentation into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'Presentation.pptx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Load the source presentation
    const sourcePpt = new pptModule.Presentation();
    sourcePpt.LoadFromFile(inputFileName);

    // Keep slides 2 to 4 (indexes start from 0)
    const startIndex = 1;
    const endIndex = 3;

    // Create a new presentation and remove its built-in blank slide
    const rangePpt = new pptModule.Presentation();
    rangePpt.Slides.RemoveAt(0);

    // Copy the slides inside the range one by one
    for (let i = startIndex; i <= endIndex; i++) {
      rangePpt.Slides.Append({ slide: sourcePpt.Slides.get_Item(i) });
    }

    const outputFileName = 'SplitRange.pptx';
    rangePpt.SaveToFile({ file: outputFileName, fileFormat: pptModule.FileFormat.Pptx2013 });

    // Release resources
    rangePpt.Dispose();
    sourcePpt.Dispose();

    // Read the result 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);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Split PowerPoint Slides by Page Range</h1>
      <button onClick={splitByRange}>
        Split by Page Range
      </button>
    </div>
  );
}

export default App;

Presentation after splitting slides by page range:

Presentation after splitting slides by page range


FAQ

Why does a split result contain an extra blank slide

Cause: The presentation created by new pptModule.Presentation() contains one blank slide by default. If the source slides are appended directly, that blank page stays at the beginning of the result.

Solution: Call Slides.RemoveAt(0) before appending slides to remove the default page, for example:

const singlePpt = new pptModule.Presentation();
singlePpt.Slides.RemoveAt(0);
singlePpt.Slides.Append({ slide: sourcePpt.Slides.get_Item(i) });

Why does an index return the wrong slide

Cause: The index of Slides.get_Item(index) starts at 0, so the first slide corresponds to index 0. Using a page number directly shifts the selection by one.

Solution: Use zero-based indexes consistently. To take slides 2 to 4, set startIndex to 1 and endIndex to 3.

Why is the last slide missing after splitting by page range

Cause: If the loop condition is written as i < endIndex, the slide at endIndex is never visited; the index range includes both ends.

Solution: Use i <= endIndex as the loop condition and make sure endIndex does not exceed sourcePpt.Slides.Count - 1.


Get a Free License

Spire.Presentation for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.