How to copy one image from a Word (365) Document to another using OpenXML?

Serge-5526794613 1 Reputation point
2021-04-11T13:52:36.95+00:00

I generate an SSRS report that I save as a Word document. That document contain pictures (charts as plat images).
I don't really save the Word document, I have it open in memory.

I use then OpenXML to create another word document, in witch I need to copy the pictures from the SSRS report.

I try to get the drawings from the ssrs report, and insert them in the new word document

MainDocumentPart ssrsMainPart = ssrsDoc.MainDocumentPart;
var drawings = ssrsMainPart.Document.Descendants<Drawing>().ToList();

and then insert them in the new document

MainDocumentPart mainPart = wordDoc.MainDocumentPart;
Body body = mainPart.Document.Body;

for (int i = 0; i < 10; i++)
{
    if (i < drawings.Count())
    {
        var myDrawing = drawings.Skip(i).First();
        myDrawing.Remove();
        body.Append(myDrawing); 
        body.Append(new Paragraph());
    }
}

As result I get in the resulting document only the picture placeholders, of the same size as in ssrs Word Document, but the pictures are empty.

I tried to copy the ImageData as well, using the following code:

foreach (var e in ssrsDoc.MainDocumentPart.Document.Body.Elements())
{
    var clonedElement = e.CloneNode(true);
    clonedElement.Descendants<DocumentFormat.OpenXml.Drawing.Blip>().ToList().ForEach(blip =>
    {
        var newRelation = wordDoc.CopyImage(blip.Embed, ssrsDoc);
        blip.Embed = newRelation;
    });
    clonedElement.Descendants<DocumentFormat.OpenXml.Vml.ImageData>().ToList().ForEach(imageData =>
    {
        var newRelation = wordDoc.CopyImage(imageData.RelationshipId, ssrsDoc);
        imageData.RelationshipId = newRelation;
    });
    wordDoc.MainDocumentPart.Document.Body.AppendChild(clonedElement);
}

with CopyImage defined like this:

public static string CopyImage(this WordprocessingDocument newDoc, string relId, WordprocessingDocument org)
{
    var p = org.MainDocumentPart.GetPartById(relId) as ImagePart;
    var newPart = newDoc.MainDocumentPart.AddPart(p);
    newPart.FeedData(p.GetStream());
    return newDoc.MainDocumentPart.GetIdOfPart(newPart);
}

but after that I wasn't able to open anymore the document with Word 365, word reporting the doc as a broken one...

Microsoft 365 and Office | Development | Other
Microsoft 365 and Office | Word | For business | Windows
Developer technologies | C#
{count} votes

2 answers

Sort by: Most helpful
  1. Obaid Farooqi MSFT 751 Reputation points Microsoft Employee Moderator
    2021-04-11T23:45:23.943+00:00

    Hi @Serge-5526794613 :
    the tag openspecs-office is dedicated to supporting issues related to open specifications. The open specifications are available at https://learn.microsoft.com/en-us/openspecs/

    Your inquiry is not related to open specifications. For a better chance of getting an answer, you may want to post your inquiry at open XML SDK issues on github at the following link:
    https://github.com/OfficeDev/Open-XML-SDK/issues

    I have removed the openspecs-office tag from your posting.

    Regards,
    Obaid Farooqi - MSFT


  2. Timon Yang-MSFT 9,606 Reputation points
    2021-04-12T02:39:13.69+00:00

    This is an example of inserting a local image file into another MS Word file.

    You can get the image from the stream and modify part of the code to make it suitable for your situation.

    using System.IO;  
    using DocumentFormat.OpenXml;  
    using DocumentFormat.OpenXml.Packaging;  
    using DocumentFormat.OpenXml.Wordprocessing;  
    using A = DocumentFormat.OpenXml.Drawing;  
    using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;  
    using PIC = DocumentFormat.OpenXml.Drawing.Pictures;  
      
    namespace ConsoleApp2  
    {  
        class Program  
        {  
        static void Main(string[] args)  
        {  
            string sourcefile = @"D:\test\word\1.docx";  
            string targetFile = @"D:\test\word\2.docx";  
            CopyImage(sourcefile, targetFile);  
        }  
        public static void CopyImage(string sourcefile, string targetFile)   
        {  
            using (WordprocessingDocument wordDoc1 = WordprocessingDocument.Open(sourcefile, false))  
            using (WordprocessingDocument wordDoc2 = WordprocessingDocument.Open(targetFile, true))  
            {  
                foreach (ImagePart ipt in wordDoc1.MainDocumentPart.ImageParts)  
                {  
                    ImagePart newIpt = wordDoc2.MainDocumentPart.AddPart<ImagePart>(ipt);  
                    AddImageToBody(wordDoc2, wordDoc2.MainDocumentPart.GetIdOfPart(newIpt));  
                }  
    
            }  
        }  
      
            private static void AddImageToBody(WordprocessingDocument wordDoc, string relationshipId)  
            {  
                // Define the reference of the image.  
                var element =  
                  new Drawing(  
                    new DW.Inline(  
                      new DW.Extent() { Cx = 990000L, Cy = 792000L },  
                      new DW.EffectExtent()  
                      {  
                          LeftEdge = 0L,  
                          TopEdge = 0L,  
                          RightEdge = 0L,  
                          BottomEdge = 0L  
                      },  
                      new DW.DocProperties()  
                      {  
                          Id = (UInt32Value)1U,  
                          Name = "Picture 1"  
                      },  
                      new DW.NonVisualGraphicFrameDrawingProperties(  
                          new A.GraphicFrameLocks() { NoChangeAspect = true }),  
                      new A.Graphic(  
                        new A.GraphicData(  
                          new PIC.Picture(  
                            new PIC.NonVisualPictureProperties(  
                              new PIC.NonVisualDrawingProperties()  
                              {  
                                  Id = (UInt32Value)0U,  
                                  Name = "New Bitmap Image.jpg"  
                              },  
                              new PIC.NonVisualPictureDrawingProperties()),  
                            new PIC.BlipFill(  
                              new A.Blip(  
                                new A.BlipExtensionList(  
                                  new A.BlipExtension()  
                                  {  
                                      Uri = "{28A0092B-C50C-407E-A947-70E740481C1C}"  
                                  })  
                               )  
                              {  
                                  Embed = relationshipId,  
                                  CompressionState =  
                                  A.BlipCompressionValues.Print  
                              },  
                              new A.Stretch(  
                                new A.FillRectangle())),  
                              new PIC.ShapeProperties(  
                                new A.Transform2D(  
                                  new A.Offset() { X = 0L, Y = 0L },  
                                  new A.Extents() { Cx = 990000L, Cy = 792000L }),  
                                new A.PresetGeometry(  
                                  new A.AdjustValueList()  
                                )  
                                { Preset = A.ShapeTypeValues.Rectangle }))  
                        )  
                        { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" })  
                    )  
                    {  
                        DistanceFromTop = (UInt32Value)0U,  
                        DistanceFromBottom = (UInt32Value)0U,  
                        DistanceFromLeft = (UInt32Value)0U,  
                        DistanceFromRight = (UInt32Value)0U  
                    });  
                // Append the reference to body, the element should be in a Run.  
                wordDoc.MainDocumentPart.Document.Body.Append(new Paragraph(new Run(element)));  
            }  
        }  
    }  
    

    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.