Author Archive

Creating New Presentations from Slide Masters Using OpenXML (Revisited)

May 4, 2010

Here’s an update to a prior post, Creating New Presentations from Slide Masters Using OpenXML, about creating new presentation slides from the slide master.  A reader commented about an error with layouts that had images in them and it came to my attention that my code completely ignored the images.  Here’s an update:

private static void InsertSlide(PresentationPart pPart, string layoutName, UInt32 slideId)

        {

            Slide slide = new Slide(new CommonSlideData(new ShapeTree()));

            SlidePart sPart = pPart.AddNewPart<SlidePart>();

            slide.Save(sPart);

            SlideMasterPart smPart = pPart.SlideMasterParts.First();

            SlideLayoutPart slPart = smPart.SlideLayoutParts.Single(kaark => kaark.SlideLayout.CommonSlideData.Name == layoutName);

            //Add the layout part to the new slide from the slide master

            sPart.AddPart<SlideLayoutPart>(slPart);

            sPart.Slide.CommonSlideData = (CommonSlideData)smPart.SlideLayoutParts.Single(kaark => kaark.SlideLayout.CommonSlideData.Name == layoutName).SlideLayout.CommonSlideData.Clone();

 

            using (Stream stream = slPart.GetStream())

            {

                sPart.SlideLayoutPart.FeedData(stream);

            }

 

            //UPDATED: Copy the images from the slide master layout to the new slide

            foreach (ImagePart iPart in slPart.ImageParts)

            {

                ImagePart newImagePart = sPart.AddImagePart(iPart.ContentType, slPart.GetIdOfPart(iPart));

                newImagePart.FeedData(iPart.GetStream());

            }

 

            SlideId newSlideId = pPart.Presentation.SlideIdList.AppendChild<SlideId>(new SlideId());

            newSlideId.Id = slideId;

            newSlideId.RelationshipId = pPart.GetIdOfPart(sPart);

        }

After feeding the slide layout part data into the new slide’s layout part, the code then adds the new image parts to the slide from the slide master layout.

Creating New Presentations from Slide Masters Using OpenXML

March 24, 2010

The slide master in Powerpoint provides a powerful way for end-users to easily control the appearance and layouts of a presentation.  A slide master contains a set of layouts that are subsequently used by the slides in the presentation.

A common approach to constructing  a new presentation is to have a template with slides that are then copied/merged into the new presentation.  The approach I will be demonstrating creates slides in the new presentation based off the slide master layouts in the template.  This approach still requires a template, but does not require slides to already exist. 

The Template

The template I used contained a few layouts in the slide master, each arranged with some placeholder objects.  A great benefit of layouts in the slide master is that they can be renamed through the UI.  The layout name is what will be used in the code to construct the slide deck in the new presentation.

The Code

Now the fun part.  The InsertSlide method takes a PresentationPart, layout name from the slide master, and ID for the new slide.  It creates the new Slide and adds the associated parts to the PresentationPart, copying all the required layout and common slide data from the slide master layout.

   1: private static void InsertSlide(PresentationPart pPart, string layoutName, UInt32 slideId)

   2:         {

   3:             Slide slide = new Slide(new CommonSlideData(new ShapeTree()));

   4: 

   5:             SlidePart sPart = pPart.AddNewPart<SlidePart>();

   6:             slide.Save(sPart);

   7: 

   8:             SlideMasterPart smPart = pPart.SlideMasterParts.First();

   9:             SlideLayoutPart slPart = smPart.SlideLayoutParts.Single(kaark => kaark.SlideLayout.CommonSlideData.Name == layoutName);

  10:             sPart.AddPart<SlideLayoutPart>(slPart);

  11:             sPart.Slide.CommonSlideData = (CommonSlideData)smPart.SlideLayoutParts.Single(kaark => kaark.SlideLayout.CommonSlideData.Name == layoutName).SlideLayout.CommonSlideData.Clone();

  12:             using (Stream stream = slPart.GetStream())

  13:             {

  14:                 sPart.SlideLayoutPart.FeedData(stream);

  15:             }

  16: 

  17:             SlideId newSlideId = pPart.Presentation.SlideIdList.AppendChild<SlideId>(new SlideId());

  18:             newSlideId.Id = slideId;

  19:             newSlideId.RelationshipId = pPart.GetIdOfPart(sPart);

  20:         }

Since the presentation started with only a slide master in the template and no slides, a SlideIdList must be added to the PresentationPart.  Then start adding slides, using the layout names from the slide master.  Notice that the slide IDs were started at 256, that’s not a typo.  Slide IDs must be >= 256.

   1: using (PresentationDocument pDoc = PresentationDocument.Open(newFileCopiedFromTemplate, true))

   2:             {

   3:                 PresentationPart pPart = pDoc.PresentationPart;

   4: 

   5:                 pPart.Presentation.SlideIdList = new SlideIdList();

   6:                 InsertSlide(pPart, "Layout1", 256);

   7:                 InsertSlide(pPart, "Layout3", 257);

   8:                 InsertSlide(pPart, "Layout3", 258);

   9:                 InsertSlide(pPart, "Layout2", 259);

  10:                 pPart.Presentation.Save();

  11:                 pDoc.Close();

  12:             }