Search code examples
c#ms-wordoffice365vstoaccessibility

Set shape / inlineshape as Decorative in Word


In Office 365 Microsoft introduced a new property for Shapes / InlineShapes (pictures): Decorative

I can manipulate it using VBA as demonstrated here, but not using VSTO, which is what I really need.

The value type is Microsoft.Office.Core.MsoTriState and if set to msoTrue it enables the feature on the picture.

I've been able to toggle this feature easily using VBA, as demonstrated here (to try it, just insert an inline image in an empty document in Microsoft Word 365)

Sub ToggleDecorativePic()
    Dim pic As InlineShape
    Set pic = ActiveDocument.InlineShapes(1)
    pic.Decorative = Not pic.Decorative
End Sub

This will toggle the Decorative property of the first InLineShape in the active document.

Before code executed

After code executed

*But here's the actual problem:

I need to do this from VSTO (C# or VB.NET), but the property .Decorative is not available in Intellisense, and even if I try forcing it by typecasting the InlineShape object to Dynamic, it just crashes when executing the code.

I'm using this Office Interop nuGet bundle to interact with Word: Bundle.Microsoft.Office.Interop version 15.0.4569 dated October 23rd 2018 so it should be up-to-date. The bundle contains Interop ressources for Microsoft Excel, Outlook, PowerPoint and Word.

I also tried using Microsoft.Office.Interop.Word but it's about two years old, so it obviously doesn't contain this new feature either.

With the new EU laws regarding accessible documents, this is a critical feature when generating PDF documents using Microsoft Word.

Alternately: Is it possible to dynamically execute this as VBA somehow, from VSTO, without creating macros in the document etc.? I'm guessing no, at least not without enabling trust in the object model, which is just not a feasible option :-/


Solution

  • Interesting problem, indeed. At first, I thought it could perhaps be solved by setting the reference to Microsoft.Office.Interop.Word to the PIAs in the GAC rather than those installed by Visual Studio (which is the default source for a VSTO project) and by setting "embed interop types" to false. Both had no effect, however.

    That left only the option of using PInvoke, which did work for me:

        Word.InlineShape ils = doc.InlineShapes[1];
    
        object oIls = ils;
        object isDec = oIls.GetType().InvokeMember("Decorative", System.Reflection.BindingFlags.GetProperty, null, oIls, null);
    
        System.Diagnostics.Debug.Print("Is the InlineShape marked as decorative: " + isDec.ToString());
    
        if ((int)isDec != -1)
        {
            object[] arg = new object[] { -1 };
            oIls.GetType().InvokeMember("Decorative", System.Reflection.BindingFlags.SetProperty, null, oIls, arg);
        }