Click here to Skip to main content
15,921,841 members
Articles / Programming Languages / XML
Tip/Trick

Inserting an Image into an "inline shape" in Word Document using Microsoft Open XML SDK

Rate me:
Please Sign up or sign in to vote.
4.67/5 (4 votes)
21 Jun 2017CPOL3 min read 24.2K   4   3
How to insert an image into an "inline shape" in Word Document using Microsoft Open XML SDK

Introduction

Microsoft Open XML is a new technology that Microsoft recommends using to perform CRUD operations on Office documents (Word, Excel, Powerpoint, etc.). Microsoft recommends using OpenXML over MS Interop. Microsoft also does not recommend the use of server side automation of Microsoft Office applications through server side codes such as ASP.NET, DCOM, and WIndows NT services that use Microsoft Office Interop libraries.

Although OpenXML is the direction that Microsoft wants developers to use to manipulate office documents, it is not as easy to use as compared to using the Microsoft interop libraries. This tip will demonstrate one of the hardest challenges I faced using openXML, which is inserting an image into a shape. For Microsoft interop, this task could've been done in as much as 6 lines.

Background

Starting from Microsoft Office 2007, Open XML file format has become the default file format for Microsoft Office.

To understand this tutorial, make sure you know how to use the basics of the openxml SDK, such as opening and saving documents with C#.

This article assumes you know how to insert an image into a Word document, open and close a Word document using OpenXML. See the link below:

Using the Code

Add the following OpenXML namespaces to your class:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using DocumentFormat.OpenXml;
using A = DocumentFormat.OpenXml.Drawing;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
using DocumentFormat.OpenXml.Drawing.Wordprocessing;
using Wps = DocumentFormat.OpenXml.Office2010.Word.DrawingShape;

With the namespaces added, you can now use the required classes from OpenXML. Open the document using OpenXML. Add an imagePart that references the image object (The image you want to insert) to the MaindocumentPart object by using a file stream and get the ID of the image.

C#
string temp;
MainDocumentPart mainPart = document.MainDocumentPart;
ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Bmp);

using (FileStream stream = new FileStream(barcodepath, FileMode.Open))
{
    imagePart.FeedData(stream);
}

temp = mainPart.GetIdOfPart(imagePart);

In office OpenXML, a picture that is inserted into a Word document is considered a "Blip" Object or element. The class is derived from the DocumentFormat.OpenXml.Drawing the Blip must have an Embed value that is an imagePart ID. The Blip object then goes inside a BlipFill Object/element, and that also goes inside a graphicData Object/element and that in turn goes into a graphic object element. I'm pretty sure by now you've realized everything works like an XML tree. Sample Open XML tree below:

XML
<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
  <a:graphicData uri=
  "http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
    <wps:wsp>
      <wps:cNvSpPr>
        <a:spLocks noChangeArrowheads="1" />
      </wps:cNvSpPr>
      <wps:spPr bwMode="auto">
        <a:xfrm>
          <a:off x="0" y="0" />
          <a:ext cx="1234440" cy="1234440" />
        </a:xfrm>
        <a:prstGeom prst="roundRect">
          <a:avLst>
            <a:gd name="adj" fmla="val 16667" />
          </a:avLst>
        </a:prstGeom>
        <a:blipFill dpi="0" rotWithShape="1">
          <a:blip r:embed="Raade88ffea8d4c1b" />
          <a:stretch>
            <a:fillRect l="10000" t="10000" 
            r="10000" b="10000" />
          </a:stretch>
        </a:blipFill>
      </wps:spPr>
      <wps:bodyPr rot="0" vert="horz" 
      wrap="square" lIns="91440" tIns="45720" 
      rIns="91440" bIns="45720" anchor="t" 
      anchorCtr="0" upright="1">
        <a:noAutofit />
      </wps:bodyPr>
    </wps:wsp>
  </a:graphicData>
</a:graphic>

Now I have a reference of the image(barcode) I'm trying to add to my document. I want to insert the image into the shapes in the template document. To do this, I would have to use some LINQ to iterate through the document and get a reference to all the shapes in the document. The wps:spPr element you see in the above XML code is the XML element for the shapes in my document. The equivalent C# class is WordprocessingShape.

JavaScript
IEnumerable<DocumentFormat.OpenXml.Office2010.Word.DrawingShape.WordprocessingShape> shapes2 = 
document.MainDocumentPart.document.Body.Descendants
<DocumentFormat.OpenXml.Office2010.Word.DrawingShape.WordprocessingShape>();

Now that I have a collection of all the shape references in my document, I loop through the collection with a foreach, and through each iteration, I create a Blip object. Set the Blip object embed value to the picture ID reference I captured earlier form the image part. I also create a Stretch object, and FillRectangle object (these are not really necessary, I just used them for proper alignment of the barcode). And append each to its parent objects like the XML tree equivalent.

C#
foreach (DocumentFormat.OpenXml.Office2010.Word.DrawingShape.WordprocessingShape sp in shapes2)
  {
    A.BlipFill blipFill = new A.BlipFill() { Dpi = (UInt32Value)0U, RotateWithShape = true };
    A.Blip blip1 = new A.Blip() { Embed = temp };

   A.Stretch stretch1 = new A.Stretch();
   A.FillRectangle fillRectangle1 = new A.FillRectangle() 
      { Left = 10000, Top = 10000, Right = 10000, Bottom = 10000 };
   Wps.WordprocessingShape wordprocessingShape1 = new Wps.WordprocessingShape();

   stretch1.Append(fillRectangle1);
   blipFill.Append(blip1);
   blipFill.Append(stretch1);
   Wps.ShapeProperties shapeProperties1 = sp.Descendants<Wps.ShapeProperties>().First();
   shapeProperties1.Append(blipFill);
                                     
   }

That's pretty much it. Run the code and use a Word document that has inline shapes (rectangle, oval, etc.) and try to insert an image into them.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 4 Pin
Member 1236439025-Jun-17 20:59
Member 1236439025-Jun-17 20:59 
BugblipFill1 undefined Pin
martinrj3015-Jun-17 21:00
martinrj3015-Jun-17 21:00 
GeneralRe: blipFill1 undefined Pin
Dankwansere21-Jun-17 14:48
Dankwansere21-Jun-17 14:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.