In previous posts, I showed you how to import charts from spreadsheets to a Wordprocessing document and how to import tables from Word documents to spreadsheets. Today, I am going to show you how to import SmartArt from a PowerPoint deck into a Word document.

Solution

To import a SmartArt graphic from a PowerPoint deck to a Word document we need to take the following actions:

  1. Create a template in Word that contains a content control that will be used to demarcate the region where the SmartArt graphic will be inserted
  2. Open up the PowerPoint deck via the Open XML SDK and access the slide with the SmartArt graphic to be imported
  3. Get all the appropriate parts associated with the SmartArt graphic
  4. Retrieve necessary information from the SmartArt graphic, like name and size
  5. Open up the Word document, which will contain the imported SmartArt graphic
  6. Add all the SmartArt related parts to the Word document
  7. Create a paragraph that contains an inline SmartArt graphic, which references all the added parts
  8. Locate the content control that will contain the SmartArt graphic
  9. Swap out the content control for the created paragraph, which contains the SmartArt graphic
  10. Save changes made to the Word document

My post will talk about using version 2 of the SDK.

For the sake of this post, let's say I am starting with the following PowerPoint deck and SmartArt graphic:

Also, let's say I am starting with the following document, which contains a placeholder content control:

If you just want to jump straight into the code, feel free to download this solution here.

The Code

As described in the solution section above, steps two and three require us to open the PowerPoint deck, find the slide with the SmartArt graphic, and extract all related parts. Below is the code snippet necessary to accomplish those tasks:

using (PresentationDocument myPres = PresentationDocument.Open(presentationFile, true))
{
PresentationPart presPart = myPres.PresentationPart;
//Get the slide that contains the SmartArt graphic
SlidePart slide = (SlidePart)presPart.GetPartById("rId2");
//Get all the appropriate parts associated with the SmartArt
DiagramLayoutDefinitionPart layoutPart =
slide.DiagramLayoutDefinitionParts.First();
DiagramDataPart dataPart = slide.DiagramDataParts.First();
DiagramColorsPart colorsPart = slide.DiagramColorsParts.First();
DiagramStylePart stylePart = slide.DiagramStyleParts.First();
...
}

Note that in the code above I knew which part/slide contained the SmartArt graphic.

Next step is to retrieve some necessary information from the SmartArt graphic itself. For example, we can retrieve the name, id, extent width, and extent height. The following code snippet retrieves the SmartArt elements that contain all this information (we will use these objects later in the code):

//Get some of the appropriate properties off the SmartArt graphic
GraphicFrame graphicFrame = slide.Slide.Descendants<GraphicFrame>().First();
NonVisualDrawingProperties drawingPr =
graphicFrame.Descendants<NonVisualDrawingProperties>().First();
Draw.Extents extents = graphicFrame.Descendants<Draw.Extents>().First();

Now we get to do the fun stuff; import the SmartArt graphic into the Word document. Below is the code snippet necessary to accomplish steps five and six as mentioned in the solution section above:

//Import SmartArt into Word document
using (WordprocessingDocument myDoc = WordprocessingDocument.Open(outputFile, true))
{
MainDocumentPart mainPart = myDoc.MainDocumentPart;
//Add the SmartArt parts to the Word document
DiagramLayoutDefinitionPart docLayoutPart = mainPart.AddPart<DiagramLayoutDefinitionPart>(layoutPart);
DiagramDataPart docDataPart = mainPart.AddPart<DiagramDataPart>(dataPart);
DiagramColorsPart docColorsPart = mainPart.AddPart<DiagramColorsPart>(colorsPart);
DiagramStylePart docStylePart = mainPart.AddPart<DiagramStylePart>(stylePart);
//Get all the relationship ids of the added parts
docLayoutPartId = mainPart.GetIdOfPart(docLayoutPart);
docDataPartId = mainPart.GetIdOfPart(docDataPart);
docColorsPartId = mainPart.GetIdOfPart(docColorsPart);
docStylePartId = mainPart.GetIdOfPart(docStylePart);
...
}

Notice how we are simply importing the parts from the PowerPoint deck into the Word document. The next step is to create a paragraph object that contains the SmartArt. The easiest way to accomplish this task is to leverage the Document Reflector tool that comes with the SDK. This tool is awesome! It automatically generates SDK code based on a document or content within a document. I would recommend checking out Erika's post on how to use the Document Reflector.

Here is a screenshot of the Document Reflector in action when reading in a Word document containing a SmartArt graphic. Notice the nice C# code it generated for me.

Copying this code into my solution I get the following:

//Use the document reflector to figure out how to add a SmartArt graphic to Word
//Change attribute values based on specifics related to the SmartArt
Paragraph p = new Paragraph(
new Run(
new Drawing(
new WP.Inline(
new WP.Extent() { Cx = extents.Cx, Cy = extents.Cy },
new WP.EffectExtent() { LeftEdge = 0L, TopEdge = 0L,
RightEdge = 0L, BottomEdge = 0L },
new WP.DocProperties() { Id = drawingPr.Id, Name =
drawingPr.Name },
new WP.NonVisualGraphicFrameDrawingProperties(),
new Draw.Graphic(
new Draw.GraphicData(
new Dgm.RelationshipIds() { DataPart = docDataPartId,
LayoutPart = docLayoutPartId, StylePart = docStylePartId, ColorPart = docColorsPartId }
) { Uri = "http://schemas.openxmlformats.org/drawingml/2006/diagram" })
) { DistanceFromTop = (UInt32Value)0U, DistanceFromBottom = (UInt32Value)0U, DistanceFromLeft = (UInt32Value)0U, DistanceFromRight = (UInt32Value)0U })));

The code snippet above is pretty much a copy/paste. The only difference is that I added the correct extent width and height values as well as the proper name and ids for the SmartArt graphic.

Almost done! The next thing we need to do is find the content control within the Word document and swap out the content control for this newly created paragraph. The following code snippet accomplishes this task:

//Find the content control in Word where the SmartArt will be added
SdtBlock sdt = mainPart.Document.Descendants<SdtBlock>()
.Where(s =>
s.GetFirstChild<SdtProperties>().GetFirstChild<Alias>().Val.Value
.Equals("SmartArt")).First();
//Swap out the content control for the SmartArt
OpenXmlElement parent = sdt.Parent;
parent.InsertAfter(p, sdt);
sdt.Remove();
mainPart.Document.Save();

End Result

Putting everything together and running this code, we end up with a Word document, which contains the SmartArt imported from my deck.

Here is a screenshot of the final document:

Zeyad Rajabi