With Office 2007, Microsoft introduced a new document format called OpenXml. Its an xml based format for storing Mirosoft office documents. Technically, an Office 2007 file (pptx, docx etc) is simply a zip file containing a set of xml files and related content. You can actually, rename it to .zip and extract its contents! Although the idea is novel, the xml format itself is a little complex to work with. Microsoft does provide a OpenXML SDK to make life a little easier for programmers.
However, you’ll still need to learn a lot of tricks to get things done in OpenXml. I’ll demonstrate one such common task here. If you’re working with an OpenXml PowerPoint (pptx) file, one of the first things you may want to learn is how to clone a slide. i.e. make a copy of a slide along with all its contents. There are several sites that’ll give you code to Clone a slide. Here’s a good one which I’m using as a reference for my code: http://blogs.msdn.com/brian_jones/archive/2009/08/13/adding-repeating-data-to-powerpoint.aspx
However, I didn’t find any site that has a code which works with charts. When you clone a slide, all its parts should also be cloned for it to work properly. For eg. images are stored in a property called ImagePart. If you want images from source slide to appear in the cloned slide, you should copy the ImagePart too.
Similary charts are stored in a ChartPart. However, charts are more tricky as they refer to an embedded excel sheet that contains chart data. You’ll need to copy this excel sheet too. The following function has the sample code for charts and the embedded excel. It also has code to clone images to help you compare the differences:
public static SlidePart CloneSlidePartWithImagesAndCharts(PresentationPart presentationPart, SlidePart slideTemplate)
{
int i = presentationPart.SlideParts.Count();
//Create a new slide part in the presentation.
SlidePart newSlidePart = presentationPart.AddNewPart<SlidePart>(“newSlide” + i);
i++;
//Add the source slide content into the new slide.
newSlidePart.FeedData(slideTemplate.GetStream(FileMode.Open));
//Make sure the new slide references the proper slide layout.
newSlidePart.AddPart(slideTemplate.SlideLayoutPart, slideTemplate.GetIdOfPart(slideTemplate.SlideLayoutPart));
// copy the image parts
foreach (ImagePart ipart in slideTemplate.ImageParts)
{
ImagePart newipart = newSlidePart.AddImagePart(ipart.ContentType, slideTemplate.GetIdOfPart(ipart));
newipart.FeedData(ipart.GetStream());
}
// copy the chart parts
foreach (ChartPart cpart in slideTemplate.ChartParts)
{
ChartPart newcpart = newSlidePart.AddNewPart<ChartPart>(slideTemplate.GetIdOfPart(cpart));
newcpart.FeedData(cpart.GetStream());
// copy the embedded excel file
EmbeddedPackagePart epart = newcpart.AddEmbeddedPackagePart(cpart.EmbeddedPackagePart.ContentType);
epart.FeedData(cpart.EmbeddedPackagePart.GetStream());
// link the excel to the chart
(((newcpart.ChartSpace)).ExternalData).Id = newcpart.GetIdOfPart(epart);
newcpart.ChartSpace.Save();
}
//Get the list of slide ids.
SlideIdList slideIdList = presentationPart.Presentation.SlideIdList;
//Deternmine where to add the next slide (find max number of slides).
uint maxSlideId = 1;
SlideId prevSlideId = null;
foreach (SlideId slideId in slideIdList.ChildElements)
{
if (slideId.Id > maxSlideId)
{
maxSlideId = slideId.Id;
prevSlideId = slideId;
}
}
maxSlideId++;
//Add the new slide at the end of the deck.
SlideId newSlideId = slideIdList.InsertAfter(new SlideId(), prevSlideId);
//Make sure the id and relid are set appropriately.
newSlideId.Id = maxSlideId;
newSlideId.RelationshipId = presentationPart.GetIdOfPart(newSlidePart);
newSlidePart.Slide.Save();
return newSlidePart;
}





