Click here to Skip to main content
Click here to Skip to main content

Merge PowerPoint Presentations (PPTX) & save as PDF

, 5 Feb 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
This article describes how to merge PowerPoint Presentations (PPTX format) and save as PDF in .NET applications using Office Automation (OpenXML SDK).

Introduction    

This article will show you how to programmatically merge PowerPoint 2010 presentations into one and save the merged presentation in PDF format using Open XML, Open XML SDK 2, Microsoft Office Interop, Microsoft Office Object Library and Visual Studio 2013. 

Overview 

We have three PowerPoint 2010 presentations:

  1. SamplePresentation1.pptx
  2. SamplePresentation2.pptx 
  3. SamplePresentation3.pptx  
We’re going to merge them in to one presentation using a template TemplatePresentation.pptx. Let’s first manually merge these presentations using Microsoft PowerPoint. Following images show the input presentations and the merged presentation generated after manually copying the slides: 

TemplatePresentation.pptx  

SamplePresentation1.pptx

SamplePresentation2.pptx

SamplePresentation3.pptx

Manually Merged Presentation 

 

Merge Presentations using Open XML SDK 

Below topics list the steps to merge presentations in a Windows Forms Application.

Create a Windows Forms Application Project 

  1. Open Visual Studio 2013.  Click on File->New->Project
  2. Select Visual C#-> Windows and select the Windows Forms Application template

  3. Set the name of the presentation to PresentationMerger and select a desired location for the solution 

Design the Windows Form 

  1. Drag six buttons on the form as seen in the image below

     
  2. Drag 2 openFileDialog and 2 saveFileDialog on the form

  3. Set the properties of the controls: 

    • openFileDialog1: 

      1. Name: openFileDialogSelectPresentations

      2. MultiSelect: true

      3. Filter: PowerPoint Presentation|*.pptx

    • openFileDialog2: 

      1. Name: openFileDialogSelectTemplate

      2. Filter: PowerPoint Presentation|*.pptx

    • saveFileDialog1: 

      1. Name: saveFileDialogMerge

    • saveFileDialog2: 

      1. Name: saveFileDialogSavePdf

    • button1: 

      1. Name: btnSelectTemplate

      2. Text: Select Template to Use

    • button2: 

      1. Name: btnSelectPresentations

      2. Text: Select Presentations to Merge

    • button3: 

      1. Name: btnMergedPresentation

      2. Text: Merged Presentation

    • button4: 

      1. Name: btnConvertedPdf

      2. Text: Converted PDF

    • button5: 

      1. Name: btnMerge

      2. Text: Merge

    • button6: 

      1. Name: btnSaveAsPdf

      2. Text: Save as PDF

Create Events for the Controls 

  1. Double click btnSelectPresentations and enter the code below 

    private void btnSelectPresentations_Click(object sender, EventArgs e)
    {
        openFileDialogSelectPresentations.ShowDialog();
    }
    

  2. Double click btnSelectTemplate and enter the code below 

    private void btnSelectTemplate_Click(object sender, EventArgs e)
    {
        openFileDialogSelectTemplate.ShowDialog();
    }
    

  3. Double click buttonMergedOutput and enter the code  below 

    private void btnMergedPresentation_Click(object sender, EventArgs e)
    {
        saveFileDialogMerge.ShowDialog();
    }
    
  4. Double click btnConvertedPdf and enter the code  below 

    private void btnConvertedPdf_Click(object sender, EventArgs e)
    {
        saveFileDialogSavePdf.ShowDialog();
    }
    

 Add Reference to Open XML Assemblies 

  1. Right click References in PresentationMerger project and select Add Reference 

  2. Select DocumentFormat.OpenXml, WindowsBase, Microsoft.Office.Interop.PowerPoint and Microsoft Office 14.0 Object Library and then click OK 


     
     

Add the Code for Open XML  

  1. Add the additional using statements to reference Open XML related namespaces

    using System.IO;
    using DocumentFormat.OpenXml;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml.Presentation;
    
    using Microsoft.Office.Interop.PowerPoint;
    
  2. Create a variable to hold the unique ID for both the slide master and the slide layout.  Name the variable as uniqueId. 

    public partial class Form1 : Form
    {
        static uint uniqueId;
    

  3. Create the GetMaxSlideMasterId() method. This method will return the Slide Master ID.  Note that Slide Master IDs must be greater than or equal to 2147483648 because IDs greater than 2147483648 represent Slide Master IDs. This method loops through the elements of the Slide Master ID List and checks whether the child ID is greater than the defined max ID or not. 

    private uint GetMaxSlideMasterId(SlideMasterIdList slideMasterIdList)
    {
        // Slide master identifiers have a minimum value of greater than
        // or equal to 2147483648. 
        uint max = 2147483648;
    
        if (slideMasterIdList != null)
            // Get the maximum id value from the current set of children.
            foreach (SlideMasterId child in
                slideMasterIdList.Elements<slidemasterid>())
            {
                uint id = child.Id;
    
                if (id > max)
                    max = id;
            }
    
        return max;
    }
    </slidemasterid>

  4. Create the GetMaxSlideId() method. This method will return the Slide ID.  Note that Slide IDs must have a minimum value of greater than or equal to 256 and a maximum value of less than 2147483648.  IDs greater than 2147483648 represent Slide Master IDs. This method loops through the elements of the Slide ID List and checks whether the child ID is greater than the defined max ID. 

    private uint GetMaxSlideId(SlideIdList slideIdList)
    {
        // Slide identifiers have a minimum value of greater than or
        // equal to 256 and a maximum value of less than 2147483648. 
        uint max = 256;
    
        if (slideIdList != null)
            // Get the maximum id value from the current set of children.
            foreach (SlideId child in slideIdList.Elements<slideid>())
            {
                uint id = child.Id;
    
                if (id > max)
                    max = id;
            }
    
        return max;
    }
    </slideid>

  5. Create the  FixSlideLayoutIds() method. This method will ensure that each slide layout inside the Slide Master Part in each Presentation Part will have a unique ID. These IDs must be unique to distinguish each layout from one another. 

    private void FixSlideLayoutIds(PresentationPart presPart)
    {
        // Make sure that all slide layouts have unique ids.
        foreach (SlideMasterPart slideMasterPart in presPart.SlideMasterParts)
        {
            foreach (SlideLayoutId slideLayoutId in slideMasterPart.SlideMaster.SlideLayoutIdList)
            {
                uniqueId++;
                slideLayoutId.Id = (uint)uniqueId;
            }
    
            slideMasterPart.SlideMaster.Save();
        }
    

  6. Create the MergePresentation() method. This method merges one PowerPoint presentation to another. It does so by opening the destination PowerPoint as editable and checks if it has an existing Slide ID List.  If it doesn’t, the code will create one.

    private void MergePresentation(string sourcePresentation, string mergedPresentation)
    {
        int id = 0;
    
        // Open the destination presentation.
        using (PresentationDocument myDestDeck = PresentationDocument.Open(mergedPresentation, true))
        {
            PresentationPart destPresPart = myDestDeck.PresentationPart;
    
            // If the merged presentation does not have a SlideIdList 
            // element yet, add it.
            if (destPresPart.Presentation.SlideIdList == null)
                destPresPart.Presentation.SlideIdList = new SlideIdList();
    

    While the destination PowerPoint presentation is open, we open the source PowerPoint presentation. 

    // Open the source presentation. This will throw an exception if
    // the source presentation does not exist.
    using (PresentationDocument mySourceDeck = PresentationDocument.Open(sourcePresentation, false))
    {
        PresentationPart sourcePresPart =
            mySourceDeck.PresentationPart;
    
    

    With both PowerPoint presentations open, we loop through each through each Slide ID list of the presentation in the Presentation part of the Source PowerPoint presentation.  We then copy these parts and create new relations in to the destination PowerPoint presentation. Note that we have to get the Max Slide Master ID and the Max Slide ID before the foreach statement as this will be used to generate the incremental IDs for the new slide master ID and slide ID.

    The GetMaxSlideMasterId() and GetMaxSlideId() methods are called to ensure that we always get the last ID and incrementing it by one to ensure that all the IDs for the Master Slide ID and Slide ID are unique.

    // Get unique ids for the slide master and slide lists
    // for use later.
    uniqueId = GetMaxSlideMasterId(destPresPart.Presentation.SlideMasterIdList);
    
    uint maxSlideId = GetMaxSlideId(destPresPart.Presentation.SlideIdList);
    
    // Copy each slide in the source presentation, in order, to 
    // the destination presentation.
    foreach (SlideId slideId in
        sourcePresPart.Presentation.SlideIdList)
    {
        SlidePart sp;
        SlidePart destSp;
        SlideMasterPart destMasterPart;
        string relId;
        SlideMasterId newSlideMasterId;
        SlideId newSlideId;
    
        // Create a unique relationship id.
        id++;
        sp =
            (SlidePart)sourcePresPart.GetPartById(
            slideId.RelationshipId);
    
        relId = Path.GetFileNameWithoutExtension(sourcePresentation).Replace(" ", "_") + id;
    
        // Add the slide part to the destination presentation.
        destSp = destPresPart.AddPart<slidepart>(sp, relId);
    
        // The slide master part was added. Make sure the
        // relationship between the main presentation part and
        // the slide master part is in place.
        destMasterPart = destSp.SlideLayoutPart.SlideMasterPart;
        destPresPart.AddPart(destMasterPart);
    
        // Add the slide master id to the slide master id list.
        uniqueId++;
        newSlideMasterId = new SlideMasterId();
        newSlideMasterId.RelationshipId =
            destPresPart.GetIdOfPart(destMasterPart);
        newSlideMasterId.Id = uniqueId;
    
        destPresPart.Presentation.SlideMasterIdList.Append(
            newSlideMasterId);
    
        // Add the slide id to the slide id list.
        maxSlideId++;
        newSlideId = new SlideId();
        newSlideId.RelationshipId = relId;
        newSlideId.Id = maxSlideId;
    
        destPresPart.Presentation.SlideIdList.Append(newSlideId);
    }
    
    </slidepart>

    Next, we make sure that all Slide IDs are unique in the destination PowerPoint presentation by calling the FixSlideLayoutIds() method. Once everything is hunky-dory, we can then save the destination PowerPoint Presentation. 

    // Make sure that all slide layout ids are unique.
        FixSlideLayoutIds(destPresPart);
    }
    
    // Save the changes to the destination deck.
    destPresPart.Presentation.Save();
    
    

  7. Create click event for buttonMerge.  Double click buttonMerge. Add the variables below to store selected template, selected source presentations and target merged PowerPoint presentation. 

    private void btnMerge_Click(object sender, EventArgs e)
    {
        string presentationTemplate = openFileDialogSelectTemplate.FileName;
        string[] presentationsToBeMerged = openFileDialogSelectPresentations.FileNames;
        string mergedPresentation = saveFileDialogMerge.FileName;
    

  8. Create a copy of the template presentation to generate the new presentation. 

    // Create a copy of template presentation to generate merged presentation
    File.Copy(presentationTemplate, mergedPresentation, true);
    

  9. Loop through each selected source PowerPoint presentations and call the MergePresentationSlides() method 

    // Loop through each source presentation and merge the slides into 
    // the merged presentation.
    foreach (string sourcePresentation in presentationsToBeMerged)
        MergePresentation(sourcePresentation, mergedPresentation);
    

Convert the Merged Presentation to PDF 

OpenXML SDK can’t convert any Office document to another format, it can only be used to edit and manipulate the document and it does an excellent job with it as it is based on SDK and is suitable for server side operations. 

To convert an Office document to PDF, I used Microsoft Office Interop. Double click btnSaveAsPdf button and use the following code to call ConvertToPdf() method and convert the merged presentation to PDF.   

private void btnSaveAsPdf_Click(object sender, EventArgs e)
{
    // Get the source PPTX file
    String pptxFile = saveFileDialogMerge.FileName;

    // Get the destination PDF file
    String pdfFile = saveFileDialogSavePdf.FileName;

    // Convert PPTX to PDF
    ConvertToPdf(pptxFile, pdfFile);

}

Below is the ConverToPdf() method which creates an instance of PowerPoint application, loads the merged PPTX and converts it to PDF: 

public void ConvertToPdf(String pptxFile, String pdfFile)
{
    try
    {
        // Create instance of PowerPoint application
        Microsoft.Office.Interop.PowerPoint.Application ppApp = new
            Microsoft.Office.Interop.PowerPoint.Application();

        // Open the PowerPoint presentation that needs to be converted
        Microsoft.Office.Interop.PowerPoint.Presentation presentation = ppApp.Presentations.Open
            (pptxFile, Microsoft.Office.Core.MsoTriState.msoTrue,
                Microsoft.Office.Core.MsoTriState.msoFalse,
                Microsoft.Office.Core.MsoTriState.msoFalse);

        // Save the file as PDF
        presentation.ExportAsFixedFormat(pdfFile,
                        PpFixedFormatType.ppFixedFormatTypePDF,
                        PpFixedFormatIntent.ppFixedFormatIntentPrint,
                        Microsoft.Office.Core.MsoTriState.msoFalse,
                        PpPrintHandoutOrder.ppPrintHandoutHorizontalFirst,
                        PpPrintOutputType.ppPrintOutputSlides,
                        Microsoft.Office.Core.MsoTriState.msoFalse,
                        null,
                        PpPrintRangeType.ppPrintAll,
                        "",
                        false,
                        false,
                        false,
                        true,
                        true,
                        System.Reflection.Missing.Value);

        // Close the presentation
        presentation.Close();

        // Free the memory
        presentation = null;
        ppApp = null;
        GC.Collect();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.StackTrace);
        throw ex;
    }
}

Running the Code 

  1. Hit F5        
  2.  Click on Select Template to Merge button 
  3. Inside the Presentations folder which is found in the solution directory, select TemplatePresentation.pptx and click Open
  4. Click on Select Presentations to Merge button
  5. Inside the Presentations folder which is found in the solution directory, select "SamplePresentation1.pptx" "SamplePresentation2.pptx" "SamplePresentation3.pptx" and click Open
  6. Click on the Merged Presentation button
  7. Select a location for the merged presentation and give it a name that ends with .pptx and click on the Save button
  8. Click on the Merge button. Now the presentations are merged
  9. Click on the Converted PDF button
  10. Select a location for the converted PDF and give it a name that ends with .pdf and click on the Save button
  11. Click on the Save as PDF button. Now the merged presentation has been converted to PDF. Following images show the merged presentation and converted PDF 

Merged Presentation  

Merged PPDF  

Alternate Approach  

The above solution does the job using open source and free components but this solution is for PPTX only. What if you want to do the same with PPT and other presentation formats? Also, you can see from the source code that the number of lines required just doing the merging of presentations is more than expected. In real world, developers also have to handle the business requirements and integrate other complex logic like editing, replacing some words, copy different amount of slides etc. The complexity increases with the increasing number of operations. 

Below is the code using a commercial .net powerpoint component for your review that does the same job: 

private void btnMerge_Click(object sender, EventArgs e)
{
    string[] presentationsToBeMerged = openFileDialogSelectPresentations.FileNames;
    string mergedPresentation = saveFileDialogMerge.FileName;

    // Create empty presentation
    Aspose.Slides.Presentation destinationPresentation = new Aspose.Slides.Presentation();

    // Loop through each source presentation and merge the slides into 
    // the merged presentation.
    foreach (string presentation in presentationsToBeMerged)
    {
        // Open the source presentation
        Aspose.Slides.Presentation sourcePresentation = new Aspose.Slides.Presentation(presentation);
        // Get the slides of source presentation
        foreach (Aspose.Slides.Slide slide in sourcePresentation.Slides)
        {
            // Keep adding the slides in merged presentation
            destinationPresentation.Slides.AddClone(slide);
        }
    }

    // Save the merged presentation
    destinationPresentation.Save(mergedPresentation, Aspose.Slides.Export.SaveFormat.Pptx);
}

private void btnSaveAsPdf_Click(object sender, EventArgs e)
{
    // Get the merged PPTX file
    String pptxFile = saveFileDialogMerge.FileName;

    // Get the destination PDF file
    String pdfFile = saveFileDialogSavePdf.FileName;

    // Open the merged presentation
    Aspose.Slides.Presentation mergedPresentation = new Aspose.Slides.Presentation(pptxFile);

    // Convert PPTX to PDF
    mergedPresentation.Save(pdfFile, Aspose.Slides.Export.SaveFormat.Pdf);

}

You can notice that you just need to call Presentation.Slides.AddClone() method to merge presentations and Save() method to save the presentation as PPTX, PPT, PDF and many other formats. So just one line of code merges the presentations and a single line of code is enough to convert. 

The code is very clean, but there is a price factor associated with third party libraries. You have to evaluate for yourself whether a third party library is suitable for your requirements or free/open source components are enough. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

LazyCoder0
Instructor / Trainer
United States United States
I'm a developer with experience in document management solutions using Office Automation (VSTO), Open XML SDK and also commercial libraries like Aspose.

Comments and Discussions

 
QuestionHow to search-and-replace path of videos in Open XML Pinmemberkalsa9-Jun-14 0:39 
QuestionWhile opening Merged PPTX file it's showing error. Pinmembertirumala1585-May-14 1:21 
AnswerRe: While opening Merged PPTX file it's showing error. PinmemberLazyCoder05-May-14 23:23 
Questionfew questions Pinmemberhongdida12-Feb-14 20:33 
AnswerRe: few questions [modified] PinmemberLazyCoder014-Feb-14 20:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141223.1 | Last Updated 6 Feb 2014
Article Copyright 2014 by LazyCoder0
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid