-1

I'm currently working on a project where I need to programmatically add images to a Word document in C#. I've been following the official documentation and various tutorials, but I seem to be running into an issue where the image is not being added to the correct location within the Word document. The images are added to media/image.jpg instead of word/media/image.jpg.

Here's a simplified version of the code I'm using:


class Program
{
    static DocumentFormat.OpenXml.UInt32Value ID = 1;

    public static void AddBase64ImageToWordDocument(MainDocumentPart mainPart, string base64String)
    {
        //Uri imageUri = new Uri("/word/media/" + System.IO.Path.GetFileName(fileName), UriKind.Relative);


        // Convert the base64 string to bytes
        byte[] imageBytes = Convert.FromBase64String(base64String);

            Body body = mainPart.Document.Body;

            // Create a paragraph to hold the image
            var paragraph = new DocumentFormat.OpenXml.Wordprocessing.Paragraph();

            // Create a Run to hold the image
            var run = new DocumentFormat.OpenXml.Wordprocessing.Run();

            var runProperties1 = new DocumentFormat.OpenXml.Wordprocessing.RunProperties();
            NoProof noProof1 = new NoProof();

            runProperties1.Append(noProof1);
            run.Append(runProperties1);

        // Create a Drawing object to hold the image data
        Drawing drawing = new Drawing();

            // Create the inline image object
            DW.Inline inline = new DW.Inline();

            // Create the extent and the graphic data for the image
            DW.Extent extent = new DW.Extent() { Cx = 3370025L, Cy = 3408129L }; // Set the image size (in EMUs) //ooh I need to come back to you
            A.Graphic graphic = new A.Graphic();
        

        var picture = new DocumentFormat.OpenXml.Wordprocessing.Picture();

        picture.AddNamespaceDeclaration("pic", "http://schemas.openxmlformats.org/drawingml/2006/picture");

        // Create the ImagePart and add the image bytes to it
        var newUri = new Uri("word/media/image" + ID + ".jpg", UriKind.RelativeOrAbsolute);
        var stringUri = ("word/media/image" + ID + ".jpg");
        ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Jpeg);


        string relationshipId = mainPart.GetIdOfPart(imagePart);
        //mainPart.AddExternalRelationship( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml", newUri, relationshipId);
        var relationship = mainPart.Parts.FirstOrDefault(p => p.RelationshipId == relationshipId);
        //relationship.TargetUri = newUri;

        var imagePath = imagePart.Uri;
        Console.WriteLine(imagePath);


        //imagePart.AddExternalRelationship("Internal", newUri);

        using (MemoryStream stream = new MemoryStream(imageBytes))
            {
                imagePart.FeedData(stream);
            }
        A.GraphicData graphicData = (GenerateGraphicData(mainPart, imagePart)); //new A.GraphicData() { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" };

        string imageRelId = mainPart.GetIdOfPart(imagePart);
        mainPart.AddExternalRelationship("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image", new Uri("media/image.jpg", UriKind.Relative), imageRelId);

        // Set the image properties
        ID++;

            // Create the picture data and set its properties
            A.BlipFill blipFill = new A.BlipFill();
            A.Blip blip = new A.Blip() { Embed = mainPart.GetIdOfPart(imagePart) };

        A.Stretch stretch = new A.Stretch();
            A.FillRectangle fillRectangle = new A.FillRectangle();
            stretch.Append(fillRectangle);
            blipFill.Append(blip, stretch);

            // Create the shape properties
            A.ShapeProperties shapeProperties = new A.ShapeProperties();

            // Append the image parts to the picture
            //picture.Append(blipFill, shapeProperties);

            // Append the picture to the graphic data
            //graphicData.Append(picture);
            graphic.Append(graphicData);

            // Append the graphic to the inline image
            inline.Append(new DW.Extent() { Cx = extent.Cx, Cy = extent.Cy }, new DW.EffectExtent() { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L }, new DW.DocProperties() { Id = 1U, Name = "Image" }, graphic);

            // Append the inline image to the drawing object
            drawing.Append(inline);

            // Append the drawing object to the run
            run.Append(drawing);

            // Append the run to the paragraph
            paragraph.Append(run);

            // Append the paragraph to the body
            body.Append(paragraph);
    }

    static void Main(string[] args)
    {
        string processedDocFilePath = "PathToGeneratedDocument.docx";
        using (var newDoc = WordprocessingDocument.Create(processedDocFilePath, WordprocessingDocumentType.Document, true))
        {
            MainDocumentPart mainPart = newDoc.AddMainDocumentPart();
            new Document(new Body()).Save(mainPart);

            string base64Image = "YourBase64ImageString"; // Actual base64 image string
            AddBase64ImageToWordDocument(mainPart, base64Image);
        }
    }
}

The relationships might not be set up correctly. I've tried different variations of the code and URI generation, but I'm not sure what's causing the problem.

Has anyone encountered a similar issue or can provide guidance on how to correctly add images to a Word document using the Open XML SDK? Any help or advice would be greatly appreciated.

--UPDATE: I've used the openXML helper tool to generate an "identical" document and when I run the code it still fails to place the image within proper uri.

Mac Man
  • 1
  • 1
  • The best way to figure out how to do something with the OpenXML SDK is to download the "OpenXML SDK Productivity Tool" from Github. Then, in Word, create a simple Word document, save it, then add the feature you want (an image) and save it under another name. Then, within the Productivity Tool, open and Diff the two files. The reflected code will represent the difference - the insertion of the image. Presto! – Flydog57 Aug 09 '23 at 23:19
  • Thank you @Flydog57, but I've been working with the productivity tool for awhile now. As it happens, this particular piece seems to be too high-level for the code to reflect – Mac Man Aug 10 '23 at 15:23
  • 1
    Your success with using any of those tools depends upon the version of Office that you're using. One can actually rename a _.docx_ file to _.zip_ then unzip it. Then one can view the XML files. – Tu deschizi eu inchid Aug 10 '23 at 20:02

0 Answers0