Merge PowerPoint Slides with JavaScript in React

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

Combining several presentations into one is a common step when organizing report materials: a main report and a topic appendix may be prepared by different team members, and finally need to sit in one file in a consistent order; sometimes only a few conclusion pages from the appendix are needed. Copying and pasting by hand takes time and may break the layout, charts, or text styles of the original slides. Handling it on a server also requires uploading the files to a third-party environment first.

This article uses Spire.Presentation for JavaScript to merge 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.


Merge multiple PowerPoint presentations

A complete report often consists of materials from several sources, for example a main report and a topic appendix prepared by different members that finally need to be combined into one file. To merge multiple presentations, load each source file in turn, then append all of its slides to one new presentation to obtain a merged result that contains every page.

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

The steps are:

  1. Load Presentation.pptx and SlidesToMerge.pptx into the VFS with window.spire.FetchFileToVFS.
  2. Create a new presentation with new pptModule.Presentation() and remove the default blank page with Slides.RemoveAt(0).
  3. For each source file, create a Presentation instance and load it with LoadFromFile, loop over Slides.Count, take each slide with Slides.get_Item(i), and append it to the merged result with Slides.Append({ slide }).
  4. Release each source instance with Dispose() when it has been processed; after all slides are appended, save the result as MergedPresentation.pptx with SaveToFile.
  5. Read the merged result through window.dotnetRuntime.Module.FS.readFile, build a Blob, and trigger the browser download.
function App() {
  const mergePresentations = 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 two sample presentations into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const sourceFileNames = ['Presentation.pptx', 'SlidesToMerge.pptx'];
    for (const fileName of sourceFileNames) {
      await window.spire.FetchFileToVFS(fileName, '', `${process.env.PUBLIC_URL}data/`);
    }

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

    // Append all slides of every source presentation to the merged result
    for (const fileName of sourceFileNames) {
      const sourcePpt = new pptModule.Presentation();
      sourcePpt.LoadFromFile(fileName);

      for (let i = 0; i < sourcePpt.Slides.Count; i++) {
        mergedPpt.Slides.Append({ slide: sourcePpt.Slides.get_Item(i) });
      }

      sourcePpt.Dispose();
    }

    const outputFileName = 'MergedPresentation.pptx';
    mergedPpt.SaveToFile({ file: outputFileName, fileFormat: pptModule.FileFormat.Pptx2013 });
    mergedPpt.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>Merge PowerPoint Presentations</h1>
      <button onClick={mergePresentations}>
        Merge Multiple Presentations
      </button>
    </div>
  );
}

export default App;

Presentation after merging multiple presentations:

Presentation after merging multiple presentations


Merge selected PowerPoint slides

A merge does not always need every page of a source file. For example, the main report keeps its full structure, while only the two conclusion pages of the topic appendix are required. In this case, merge all slides of the main report first, then pick pages from the other presentation by index, so unrelated content is not carried over.

Code Result
mergedPpt.Slides.Append({ slide }) Appends one slide to the end of the merged result
mainPpt.Slides.Count Total number of slides in the main report
mainPpt.Slides.get_Item(i) The (i+1)-th slide of the main report (index starts at 0)
extraPpt.Slides.get_Item(index) The slide at the given index in the appendix
selectedIndexes Indexes of the appendix slides that take part in the merge

The steps are:

  1. Load the font, Presentation.pptx, and SlidesToMerge.pptx with window.spire.FetchFileToVFS.
  2. Create two Presentation instances and load both source files with LoadFromFile; create the merged result with new pptModule.Presentation() and remove the default blank page with Slides.RemoveAt(0).
  3. Loop over mainPpt.Slides.Count and append every slide of the main report with Slides.get_Item(i) and Slides.Append({ slide }).
  4. Set selectedIndexes (indexes start at 0) and append only those slides with extraPpt.Slides.get_Item(index); all other slides do not take part in the merge.
  5. Save the result as MergedSelectedSlides.pptx with SaveToFile, then read the file through window.dotnetRuntime.Module.FS.readFile and trigger the download.
function App() {
  const mergeSelectedSlides = 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 two sample presentations into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    for (const fileName of ['Presentation.pptx', 'SlidesToMerge.pptx']) {
      await window.spire.FetchFileToVFS(fileName, '', `${process.env.PUBLIC_URL}data/`);
    }

    // Load the main report and the appendix
    const mainPpt = new pptModule.Presentation();
    mainPpt.LoadFromFile('Presentation.pptx');

    const extraPpt = new pptModule.Presentation();
    extraPpt.LoadFromFile('SlidesToMerge.pptx');

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

    // Append all slides of the main report
    for (let i = 0; i < mainPpt.Slides.Count; i++) {
      mergedPpt.Slides.Append({ slide: mainPpt.Slides.get_Item(i) });
    }

    // Append only the selected slides of the appendix (indexes start from 0)
    const selectedIndexes = [1, 2];
    for (const index of selectedIndexes) {
      mergedPpt.Slides.Append({ slide: extraPpt.Slides.get_Item(index) });
    }

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

    // Release resources
    mergedPpt.Dispose();
    mainPpt.Dispose();
    extraPpt.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>Merge Selected PowerPoint Slides</h1>
      <button onClick={mergeSelectedSlides}>
        Merge Selected Slides
      </button>
    </div>
  );
}

export default App;

Presentation after merging selected slides:

Presentation after merging selected slides


FAQ

Why is the slide order in the merged result different from the expected order

Cause: The append order follows the loop order, so files processed first come first. If the file list or loop order differs from the expected order, the page order in the result changes as well.

Solution: Arrange sourceFileNames in the required order and keep the Append loop running from the first slide to the last; the merged result then follows that order.

Why does the merged 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 merged result.

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

const mergedPpt = new pptModule.Presentation();
mergedPpt.Slides.RemoveAt(0);

Are images, tables, and hyperlinks lost after merging

Cause: Slides.Append({ slide }) copies the whole slide, and images, tables, and hyperlinks are content of the slide itself, so they enter the merged result together with the slide.

Solution: No extra handling is needed. After merging, check the images and tables directly in the result file; if a hyperlink points to an external address, make sure that address is still reachable.


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.