Search code examples
c#ms-wordvstoms-officeoffice-interop

C# VSTO Replace Image in Word Document


i'm developing a Word VSTO Add-In to handle certain Template/Export Functionality. For that, a set of Images need to be replaced at the click of a Button.

For the Replace-Image-Method, i used this Post as a Template.

I slightly modified it:

public static void ReplaceImage(ImagePath image)
{
    foreach(Microsoft.Office.Interop.Word.Shape shape in Globals.ThisAddIn.Application.ActiveDocument.Shapes)
    {
        if (shape.AlternativeText == image.ToString())
        {
            object anchor = shape.Anchor;
            Microsoft.Office.Interop.Word.Shape newShape = Globals.ThisAddIn.Application.ActiveDocument.Shapes.AddPicture(
                Constants.ImagePaths[image] /* Image Path */,
                ref Constants.Missing,
                ref Constants.Missing,
                ref Constants.Missing,
                ref Constants.Missing,
                ref Constants.Missing,
                ref Constants.Missing,
                ref anchor);
            newShape.Top = shape.Top;
            newShape.Left = shape.Left;
            newShape.Width = shape.Width;
            newShape.Height = shape.Height;
            shape.Delete();
        }
    }
    foreach(Microsoft.Office.Interop.Word.InlineShape inlineShape in Globals.ThisAddIn.Application.ActiveDocument.InlineShapes)
    {
        if (inlineShape.AlternativeText == image.ToString())
        {
            Microsoft.Office.Interop.Word.InlineShape newInlineShape = Globals.ThisAddIn.Application.ActiveDocument.InlineShapes.AddPicture(
                Constants.ImagePaths[image],
                ref Constants.Missing,
                ref Constants.Missing,
                inlineShape.Range
            );
            newInlineShape.Width = inlineShape.Width;
            newInlineShape.Height = inlineShape.Height;
            inlineShape.Delete();
        }
    }
}

Now my Issue is, that no Shapes nor InlineShapes are found in the Document. (I layzily debugged it with MessageBox.Show(InlineShapes/Shapes .Count) )

It did not work regardless if the image was in the "normal" document area, header or footer.

I identify the Images by their AltName.

Can someone help me or explain what i'm doing wrong?

Best Regards,
Oliver

Update 07/05/2023 14:27: This is the Definition of ImagePath

public enum ImagePath
{
    TitleLogo,
    Logo
}

public static Dictionary<ImagePath, string> ImagePaths = new Dictionary<ImagePath, string>()
{
    [ImagePath.TitleLogo] = Path.Combine(LocalResourceBasePath, "Images", "***_title_design.png"),
    [ImagePath.Logo] = Path.Combine(LocalResourceBasePath, "Images", "***_logo.png"),
};

Solution

  • Because I don't have your complete code, I can only guess first, and I can't test and debug.

    And plz debug to check the return value ImagePaths[image], is it the picture path you want to insert?

    And the return value image.ToString(), matches or does not match the property AlternativeText.

    The most likely problematic code is on the following two lines:

    ....AlternativeText == image.ToString()

    ImagePaths[image]

    You must make sure that the value returned by the Dictionary object ImagePaths with the key image is the correct path for the image you want to insert.

    Use StoryRanges object to access the shape of each part of the Document:

    public static void ReplaceImage(ImagePath image)
    {
        //foreach (Microsoft.Office.Interop.Word.Shape shape in Globals.ThisAddIn.Application.ActiveDocument.Shapes)
        foreach (Microsoft.Office.Interop.Word.Range sr in Globals.ThisAddIn.Application.ActiveDocument.StoryRanges)
        {
            foreach (Microsoft.Office.Interop.Word.Shape shape in sr.ShapeRange)
            {
                if (shape.AlternativeText == image.ToString())
                {
                    object anchor = shape.Anchor;
                    Microsoft.Office.Interop.Word.Shape newShape =
                        Globals.ThisDocument.Shapes.AddPicture(                            
    
                        // Should be ImagePaths not Constants.ImagePaths 
                        //Constants.ImagePaths[image] /* Image Path */,
                        ImagePaths[image] /* Image Path */,
                        //ref Constants.Missing
                        //ref Constants.Missing,
                        //ref Constants.Missing,
                        //ref Constants.Missing,
                        //ref Constants.Missing,
                        //ref Constants.Missing,
                        Anchor: ref anchor);
                    newShape.Top = shape.Top;
                    newShape.Left = shape.Left;
                    newShape.Width = shape.Width;
                    newShape.Height = shape.Height;
                    shape.Delete();
                }
            }
            //foreach (Microsoft.Office.Interop.Word.InlineShape inlineShape in Globals.ThisAddIn.Application.ActiveDocument.InlineShapes)
            foreach (Microsoft.Office.Interop.Word.InlineShape inlineShape in sr.InlineShapes)
            {
                if (inlineShape.AlternativeText == image.ToString())
                {
                    //Microsoft.Office.Interop.Word.InlineShape newInlineShape = Globals.ThisAddIn.Application.ActiveDocument.InlineShapes.AddPicture(
                    Microsoft.Office.Interop.Word.InlineShape newInlineShape = sr.InlineShapes.AddPicture(
                        //Constants.ImagePaths[image],
                        ImagePaths[image],
                        //ref Constants.Missing,
                        //ref Constants.Missing,
                        Range: inlineShape.Range
                    );
                    newInlineShape.Width = inlineShape.Width;
                    newInlineShape.Height = inlineShape.Height;
                    inlineShape.Delete();
                }
            }
        }
    }