Cloning a Slide using Open Xml SDK 2.0

I need to create a presentation with quite recurring contents. So first created a template presentation using Powerpoint. Then I tried to unpack and modify with XSL. I did this with word before, and was quite happy. But for PPTX you have to create two new files per slide. That ended in a mess.

That brought me to the Open Xml SDK 2.0. Still a mess, but it is a little better.

I want to clone a template slide multiple times, and then “inject” my contents into the predefined shapes. That should be easy.

But it took me a while to find out how to correctly clone a slide. So I thought I’d share that with you.

var presentationFile = "SomeFile.pptx";
using (PresentationDocument presentationDocument 
    = PresentationDocument.Open(presentationFile, true))
{
    var presentationPart = presentationDocument.PresentationPart;
    var templatePart = presentationPart.GetSlidePartsInOrder().Last();

    var newSlidePart = templatePart.CloneSlide();

    presentationPart.AppendSlide(newSlidePart);
}

The real code…

… is in this extensions. I created something to find slide parts in the right order, because the order of slide parts stored can be different to the order they appear in. Then I created a utility that clones a slide, and another one that appends the new slide part to the presentation part, which will finally show it.

public static class OpenXmlUtils
{
    public static IEnumerable<SlidePart> GetSlidePartsInOrder(this PresentationPart presentationPart)
    {
        SlideIdList slideIdList = presentationPart.Presentation.SlideIdList;

        return slideIdList.ChildElements
            .Cast<SlideId>()
            .Select(x => presentationPart.GetPartById(x.RelationshipId))
            .Cast<SlidePart>();
    }

    public static SlidePart CloneSlide(this SlidePart templatePart)
    {
        // find the presentationPart: makes the API more fluent
        var presentationPart = templatePart.GetParentParts()
            .OfType<PresentationPart>()
            .Single();

        // clone slide contents
        Slide currentSlide = (Slide)templatePart.Slide.CloneNode(true);
        var slidePartClone = presentationPart.AddNewPart<SlidePart>();
        currentSlide.Save(slidePartClone);

        // copy layout part
        slidePartClone.AddPart(templatePart.SlideLayoutPart);

        return slidePartClone;
    }

    public static void AppendSlide(this PresentationPart presentationPart, SlidePart newSlidePart)
    {
        SlideIdList slideIdList = presentationPart.Presentation.SlideIdList;

        // find the highest id
        uint maxSlideId = slideIdList.ChildElements
            .Cast<SlideId>()
            .Max(x => x.Id.Value);

        // Insert the new slide into the slide list after the previous slide.
        var id = maxSlideId + 1;

        SlideId newSlideId = new SlideId();
        slideIdList.Append(newSlideId);
        newSlideId.Id = id;
        newSlideId.RelationshipId = presentationPart.GetIdOfPart(newSlidePart);
    }
}
Advertisements

5 thoughts on “Cloning a Slide using Open Xml SDK 2.0

  1. Thanks It helped me alot . But after using that code i found that if my template contains images then it is not coping images to clone slide .

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s