wordpress hit counter
OpenXML Developer
Goodbye and Hello

OpenXmlDeveloper.org is Shutting Down

There is a time for all good things to come to an end, and the time has come to shut down OpenXmlDeveloper.org.

Screen-casts and blog posts: Content on OpenXmlDeveloper.org will be moving to EricWhite.com.

Forums: We are moving the forums to EricWhite.com and StackOverflow.com. Please do not post in the forums on OpenXmlDeveloper.org. Instead, please post in the forums at EricWhite.com or at StackOverflow.com.

Please see this blog post for more information about my plans moving forward.  Cheers, Eric

Update/Retrieve Picture Content Control in Word 2007

  • rated by 0 users
  • This post has 1 Reply |
  • Here the example is for update but can be tweaked a bit for retrieve also.
    All images in a picture content control are stored in word/image folder of the word zip package.
    As images are separate parts of the word document package, they will be linked to the main office document using relationships in word\_rels\document.xml.rels file.
    It would be something like this:
    <Relationship Id="rId4" Type="
    http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.png" />
    The above relationship id would be used in document.xml to associate the picture content control with the image.
    In document.xml there will be this line:
    <a:blip r:embed="rId4" cstate="print" /> under the sdtContent tag of the picture content control.
    Now to update the image in picture control, we need to update this relationship id.
    Before that we need to either create a new image part in the package or get the existing part.
    Here the input is "newImageFileLocation" which is the full URI of the replacement image.
    //Based on file extension, determine content type of the new part                                                          
    string contentType = System.Net.Mime.MediaTypeNames.Image.Jpeg;
    string imageExtension = Path.GetExtension(newImageFileLocation);
    switch (imageExtension)
      case ".jpeg":
      case ".jpg":
       contentType = System.Net.Mime.MediaTypeNames.Image.Jpeg;
      case ".gif":
       contentType = System.Net.Mime.MediaTypeNames.Image.Gif;
      case ".tiff":
       contentType = System.Net.Mime.MediaTypeNames.Image.Tiff;
      case ".png":
       contentType = "image/png";
    string newImageFileName = Path.GetFileName(newImageFileLocation);
    //Remove all spaces from the image name as word does not allow it
    newImageFileName = newImageFileName.Replace(" ", "");
    //Form a relative URI which identifies the new image part - it would be something like /word/media/image.jpg
    Uri newImageUri = new Uri("/word/media/" + newImageFileName, UriKind.Relative);

    //Create new image part  
    ZipPackagePart newImagePart = null;
    string newRelId = String.Empty;
     newImagePart = this.ParentWordDocument.AddNewPart(newImageUri, contentType);
     //If the user provides the byte[] of the image (imageData) then we need not download the image
     if (imageData == null)
       using (WebClient wc = new WebClient())
        wc.Credentials = CredentialCache.DefaultCredentials;
        imageData = wc.DownloadData(newImageFileLocation);
      catch (Exception ex)
       throw new Exception(string.Format("Failed retrieving image file: {0}", newImageFileLocation), ex);
     //Set the value of new image part's stream with data retrieved from new image
     MemoryStream newImageFileStream = new MemoryStream(imageData);
     //This function copies from source stream to destination stream
     Util.CopyStream((Stream)newImageFileStream, newImagePart.GetStream());
     //Create new relationship between new image part and main office document                              
     PackageRelationship newRelation = docPart.CreateRelationship(newImageUri, TargetMode.Internal, this.ParentWordDocument.ImageRelationshipType);
     newRelId = newRelation.Id;
    catch (InvalidOperationException)
      //If the new image part already exists then get the relationship id of it's relationship with main office document.
      newImagePart = this.ParentWordDocument.GetPart(newImageUri);
      foreach (PackageRelationship rel in docPart.GetRelationshipsByType(this.ParentWordDocument.ImageRelationshipType))
       if (rel.TargetUri == newImageUri)
        newRelId = rel.Id;
     catch (Exception ex)
      throw new Exception(String.Format("Failed creating new part for the image:{0}", imageUri), ex);
    Once the image part is created go ahead and update the relationship id. Here the partXml is the xml representing the main office document.
    //Update the picture control's pointer to new relationship                            
    _namespaceManager.AddNamespace("a", "http://schemas.openxmlformats.org/drawingml/2006/main");
    XmlElement controlNode = (XmlElement)partXml.DocumentElement.SelectSingleNode("//w:sdtPr/w:id[@w:val='" + _id + "']", _namespaceManager);
    XmlElement parentSDTNode = (XmlElement)controlNode.ParentNode.ParentNode;
    XmlElement contentNode = (XmlElement)parentSDTNode.SelectSingleNode("w:sdtContent", _namespaceManager);
    //Get the blip node which contains relationship id to be updated.
    XmlElement blipNode = (XmlElement)contentNode.SelectSingleNode(".//a:blip[@r:embed]", _namespaceManager);
    string oldRelationshipId = blipNode.GetAttribute("r:embed");
    if (newRelId != String.Empty)
     blipNode.Attributes["r:embed"].Value = newRelId;
    Finally save the changes made in the partXml in the office document zip package part (docPart)
    For details to the basic of office xml check the following links
    It provides the e-book about the OpenXMl markup for word 2007
    Gives basic idea about word 2007 document internals.
    Provides complete specification for Open Packaging Conventions and Markup Language Reference.
    Office Open XML Formats: Replacing PowerPoint 2007 Slide Images – It helped in finding a way to replace picture content control.
    Details about the System.IO.Packaging.Package class
  • This is exactly what I need to do, but I can't figure out the type of the variable
    in the line of code:
    newImagePart = this.ParentWordDocument.AddNewPart(newImageUri, contentType);
    I could'n find a AddNewPart method that accepts those parameters...

    Culd you help me a little bit on this, please?
Page 1 of 1 (2 items)