1

I'm trying to figure out why I cannot run a Microsoft Word macro called from a VSTO add-in written in VB. Every reference I can find says you can do this with a one-liner:

Application.Run("MacroName")

The macro itself is very simple...it just toggles the 'replace text as you type' setting (AutoCorrect.ReplaceText = Not AutoCorrect.ReplaceText). This runs perfectly when invoked from Word itself. The macro is linked to the normal.dotm template so it's available whenever Word is opened. I'm using a button on the Word ribbon with a callback to a function that in-turn calls the macro.

Public Function DisplayHelp(ByVal control As Office.IRibbonControl)

    'On Error Resume Next
    Dim wdApp As New Microsoft.Office.Interop.Word.Application        
    wdApp.Run("AC_Test")
    UpdateLabel()

End Function

Clicking the button does not change the state of the replace text setting. I'm somewhat inexperienced at add-in development so appreciate any suggestions.

Thanks

Pᴇʜ
  • 56,719
  • 10
  • 49
  • 73
rimetree
  • 23
  • 3
  • Have a look at https://stackoverflow.com/questions/1735815/how-to-run-existing-word-vba-macros-from-c-sharp-ribbon-addin – Sam Jun 01 '18 at 20:51
  • Where is the code for changing the replace text? Did you try to debug the code? – Eugene Astafiev Jun 01 '18 at 22:33
  • Well, I was trying to keep the code for doing replace text inside the add-in as opposed to calling a macro. But, for some reason, even though the Word application object is available, if I try to use it to change the state of AutoCorrect.ReplaceText it does not change the setting. The only way I've been able to change it programmatically is in a macro. – rimetree Jun 03 '18 at 01:26

3 Answers3

0

Make sure the VBA sub is declared in the default VBA module. You can read more about that in the Interop Between VBA and Visual Studio Office Solutions (VSTO) article.

Also sometimes helps to specify all parameters explicitly passing Type.Missing for default values. For example:

 Application.Run("Test",
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
            Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

Note, your VBA sub should declared as public.

See Application.Run for more information.

Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45
0

In a VSTO add-in you should not be starting a new Word.Application. The macro call is running in this new instance of Word that you're not seeing. It's not running in the application instance your VSTO Add-in is running in, where you clicked the button.

(Also, starting a new instance of Word as you are could leave "orphaned" instances of winword.exe running that aren't being cleaned up (memory leak) since you're not handling/releasing the object as far as you show us.)

In order to address the Word.Application from within your VSTO add-in use Globals.ThisAddin.Application. So, for example:

 Word.Application wdApp = Globals.ThisAddin.Application
 wdApp.Run("AC_Test")

Reference in the documentation material on MSDN: Global access to objects in Office projects and Program VSTO Add-ins

Note that sometimes Word is not clear on where a macro is located. In such cases you may need to include the Module Name of the macro, or even the full path to the dotm containing the macro. That isn't likely to be a problem with Normal.dotm, however...

Cindy Meister
  • 25,071
  • 21
  • 34
  • 43
  • Thanks, this helped me figure out a solution. In fact, I didn't even have to call the macro to make the change to replace text, which is even better. – rimetree Jun 04 '18 at 18:52
  • @rimetree Agreed, that would be better :-) But a good Q&A pair, anyway, since people are often confused about the question you asked! – Cindy Meister Jun 05 '18 at 13:50
0

Maybe someone will find it useful to create and call a macro in ms project (2016)

Add to reference Microsoft.Vbe.Interop and using

using VBIDE = Microsoft.Vbe.Interop;

link to project

 public Microsoft.Office.Interop.MSProject.Application app = new Microsoft.Office.Interop.MSProject.Application();

Creeate macro

      private void button1_Click(object sender, RibbonControlEventArgs e)
        {
            StringBuilder sb;
            sb = new StringBuilder();
            sb.Append("Sub aaa()"+"\n");
            sb.Append("Message \"m1\" " + "\n");
            sb.Append("End Sub"+"\n");
            VBIDE.VBComponent oModule;
            oModule = app.Application.ActiveProject.VBProject.VBComponents.Add(VBIDE.vbext_ComponentType.vbext_ct_StdModule);
            oModule.Name = "PMP1";
            oModule.CodeModule.AddFromString(sb.ToString());
            sb.Clear();
            sb.Append("Sub aaa2(ByVal word)" + "\n");
            sb.Append("Message word " + "\n");
            sb.Append("End Sub" + "\n");
            sb.Append("\n");
            sb.Append("Sub aaa3(ByVal word)" + "\n");
            sb.Append("Message word " + "\n");
            sb.Append("End Sub" + "\n");
            oModule = app.Application.ActiveProject.VBProject.VBComponents.Add(VBIDE.vbext_ComponentType.vbext_ct_StdModule);
            oModule.Name = "PMP2";
            oModule.CodeModule.AddFromString(sb.ToString());
        }

Call macro

 app.Application.Run("aaa3", "test");
Manul74
  • 139
  • 1
  • 6