4

I am trying to generated Presentations from different sources. Basically I have about 200 slides from a number of PowerPoint presentations. In order to accomplish this I'm using OpenXml Sdk. The flow of the program is as follows:

  • open template presentation
  • open new presentation
  • merge the slides from the second presentation into the template presentation

At the end I'm saving the new Presentation to the disk. Trying to open it with PowerPoint 2013 breaks it, with the following info: Problem signature:

Problem Event Name: APPCRASH
Application Name:   POWERPNT.EXE
Application Version:    15.0.4454.1000
Application Timestamp:  509a3abf
Fault Module Name:  oart.dll
Fault Module Version:   15.0.4605.1000
Fault Module Timestamp: 531f9b2a
Exception Code: c00000fd
Exception Offset:   00003051
OS Version: 6.2.9200.2.0.0.272.7
Locale ID:  1033

Additional information about the problem:

LCID:   1033
skulcid:    1033

Opening it with PowerPoint 2010 however works just fine. There is no problem with it.

This is the code:

private static void MergePresentation(string generatedPresentation, string presentationToBeMerged)
{
    try
    {
        int id = 0;

        // Open the destination presentation.
        using (PresentationDocument generatedPresentationDeck = PresentationDocument.Open(generatedPresentation, true))
        {
            PresentationPart generatedPresentationPart = generatedPresentationDeck.PresentationPart;

            // If the merged presentation does not have a SlideIdList 
            // element yet, add it.
            if (generatedPresentationPart.Presentation.SlideIdList == null)
            {
                generatedPresentationPart.Presentation.SlideIdList = new SlideIdList();
            }

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

                // Get unique ids for the slide master and slide lists
                // for use later.
                _uniqueId = GetMaxSlideMasterId(generatedPresentationPart.Presentation.SlideMasterIdList);

                uint maxSlideId = GetMaxSlideId(generatedPresentationPart.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);

                    //sp.Slide.Transition.Remove();

                    relId = Path.GetFileNameWithoutExtension(presentationToBeMerged).Replace(" ", "_") + id;

                    // Add the slide part to the destination presentation.
                    destSp = generatedPresentationPart.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;
                    generatedPresentationPart.AddPart(destMasterPart);

                    // Add the slide master id to the slide master id list.
                    _uniqueId++;
                    newSlideMasterId = new SlideMasterId();

                    newSlideMasterId.RelationshipId = generatedPresentationPart.GetIdOfPart(destMasterPart);

                    newSlideMasterId.Id = _uniqueId;

                    generatedPresentationPart.Presentation.SlideMasterIdList.Append(newSlideMasterId);

                    // Add the slide id to the slide id list.
                    maxSlideId++;
                    newSlideId = new SlideId();
                    newSlideId.RelationshipId = relId;
                    newSlideId.Id = maxSlideId;

                    generatedPresentationPart.Presentation.SlideIdList.Append(newSlideId);
                }

                // Make sure that all slide layout ids are unique.
                FixSlideLayoutIds(generatedPresentationPart);
            }

            // Save the changes to the destination deck.
            generatedPresentationPart.Presentation.Save();
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

/// <summary>
/// Find the maximum value of ID of all slide masters
/// </summary>
/// <param name="slideMasterIdList" />
/// <returns>
private static 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;
}

/// <summary>
/// Find the maximum ID of all slides
/// </summary>
/// <param name="slideIdList" />
/// <returns>
private static 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;
}

/// <summary>
/// Fix the IDs of all slide layouts by making sure that all the slide layout IDs in the
/// destination slide are unique.
/// </summary>
/// <param name="presPart" />
private static 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();
    }
}

The way I call the Merge function is:

string templateFilePath = @"C:\Users\mm\Desktop\testing pp\Presentation1.pptx";
string newFilePath = @"C:\Users\mm\Desktop\testing pp\Generated Presentation-105.pptx";
MergePresentation(templateFilePath, newFilePath);

Any ideas?

Thanks

dee-see
  • 23,668
  • 5
  • 58
  • 91
malutan.mircea
  • 143
  • 1
  • 2
  • 12

1 Answers1

3

I've managed to find the solution. Posting it here in case someone else ever runs into this issue.

I've used to OpenXml Sdk Validator on the generated presentation and that found the following error: The element has unexpected child element 'http://schemas.openxmlformats.org/presentationml/2006/main:notesMasterIdLst'

This directed my attention to the Notes in the slides. Removing them fixed the issue and everything works fine.

Code for deleting the Notes (even if you don't see any notes when opening presentations in PP):

 public static void RemoveNotesFromDoc(string docPath)
    {
        try
        {
            using (PresentationDocument pDoc =
                PresentationDocument.Open(docPath, true))
            {
                foreach (var slide in pDoc.PresentationPart.SlideParts)
                {
                    NotesSlidePart notes = slide.NotesSlidePart;


                    if (notes != null)
                    {
                        slide.DeletePart(slide.GetIdOfPart(slide.NotesSlidePart));
                    }
                }
            }
        }
    }
malutan.mircea
  • 143
  • 1
  • 2
  • 12