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: }
Tags: Office Open XML, PowerPoint
April 26, 2010 at 8:23 pm |
Hello, I’ve been searching for a while now and this is exactly what I’m looking for….but I continue to get an exception on line:
SlideLayoutPart slPart = smPart.SlideLayoutParts.Single(kaark => kaark.SlideLayout.CommonSlideData.Name == layoutName);
Exception >> “Sequence contains no matching element”
I’m hoping you could help. Thank you!
April 26, 2010 at 8:42 pm |
First thing I would check is that a layout with the layoutName passed to the method exists in the template. So for instance, “Layout1″ in line 6 is actually the name of a layout in the slide master. To rename a layout just right-click -> rename layout in the slide master. I’ll be happy to help more if this didn’t resolve your issue at all. Thanks.
April 27, 2010 at 8:33 pm |
First, thank you for your quick response. Sorry for not replying quicker… I did change my ‘Layout#’ to the name of the layouts I wanted. Though the new presentation did open up with the correct slides, it displayed an error prior to opening up. Using the Productivity Tool, I validated the presentation and saw that the error is in the slide.xml (relationship ‘rId2’ does not exist; at blip node). Thinking it might be an issue with my images in the master slide/layout, I deleted all the images from the template and ran the code again. The new presentation now opens up without any errors. Have you seen this before with images? Is it how the images were inserted in the template or with how I’m inserting the slides? I’ll need to see what the issue is here because we definitely need the images (logos) in the layouts.
My last question is you have a Stream/SlideLayoutPart.FeedData, why, what does it do?
Again, thanks for attention to my issue. I’m pretty new to PowerPoint OOXML and appreciate all your help!!!
April 28, 2010 at 12:46 pm |
Yes, I did find the issue with images in the layout that I wasn’t properly copying over. Later today I will post an updated piece of code that handles the images being copied properly from the slide master layout to the new slide. I’ll also give a little more info about the feed data. Thanks.
May 4, 2010 at 4:07 pm |
I have published a new post with the updated method that includes handling the images properly. Hope it fixes your issue. Thanks
May 4, 2010 at 4:00 pm |
[...] Masters Using OpenXML (Revisited) By Andrew Schwantes 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 [...]
May 6, 2010 at 3:20 pm |
Andrew, sorry for not getting back sooner. Thank you for the update….the code really helped me out. I still had the question on the Stream/SlideLayoutPart.FeedData part; sorry but if you could explain to me why you use it.
And again, thank you for your code; to insert a slide by layout was exactly what we needed!!!
August 9, 2010 at 1:09 pm |
Hi can u send me the detailled code regarding the same thing. i am having the sam erequirement but it is not working.
thanku
uday
August 10, 2010 at 3:43 am |
Hello, I’ve been searching for a while now and this is exactly what I’m looking for….but I continue to get an exception on line:
SlideLayoutPart slPart = smPart.SlideLayoutParts.Single(kaark => kaark.SlideLayout.CommonSlideData.Name == layoutName);
Exception >> “Sequence contains no matching element”
I’m hoping you could help.
I am also getting the same exception please give me reply asap
Thank you!
August 11, 2010 at 4:21 am |
Hi Andrew,
Please give me the reply, I am not able to handle the exception , SlideLayoutPart slPart = smPart.SlideLayoutParts.Single(kaark => kaark.SlideLayout.CommonSlideData.Name == layoutName);
Exception >> “Sequence contains no matching element”….
thanku
uday