7

I have a C# Excel Add-in project "MyExcelAddIn" that has a public method Foo() to do something complex. For testing purposes, the add-in also defines a toolbar button which is wired to Foo() so I can test this and verify that clicking the button calls Foo() and does what I want it to do. This is fine.

Now I want to call this method from a C# Windows Forms project. In the Windows Forms project I can create an Excel instance and make it visible and verify that my VSTO add-in is running as I can see the button and it works. But I can't work out how to call Foo() programatically from the Windows Forms project. I've googled a bit and got as far as getting the "MyExcelAddIn" COMAddIn object, but can't work out how to call Foo().

It looks something like this:

// Create Excel and make it visible
Application excelApp = new Application();
excelApp.Visible = true;

// I know my VSTO add-in is running because I can see my test button
// Now get a reference to my VSTO add-in
Microsoft.Office.Core.COMAddIns comAddIns = _excelApp.COMAddIns;
object addinName = "MyExcelAddIn";
Microsoft.Office.Core.COMAddIn myAddin = comAddIns.Item(ref addinName);
// This works, but now what? How do I make a call on myAddin?
// Note that myAddin.Object is null...

So I want to know what I can do to call Foo() from my Windows Forms application. Note that I have full control over both the Windows Forms application and the add-in and I suspect I have to make changes to both of them (particularly the add-in) but I have no idea how to do this.

Note that this is a VS2008 C# application and I'm using Excel 2003.

Mihai Limbășan
  • 64,368
  • 4
  • 48
  • 59
Ben Robbins
  • 2,889
  • 2
  • 31
  • 32

4 Answers4

5

If you're building an application-level add-in, I believe this may be your answer: MSDN VSTO Article

It involves two steps: (From the article)

  1. In your add-in, expose an object to other solutions.
  2. In another solution, access the object exposed by your add-in, and call members of the object.

The other solution may be: (Again from the article)

  • Any solution that is running in a different process than your add-in (these types of solutions are also named out-of-process clients). These include applications that automate an Office application, such as a Windows Forms or console application, and add-ins that are loaded in a different process.
Michael Regan
  • 1,568
  • 16
  • 17
1

I'm using the SendMessage Win32 API to do this. My C# Add-in creates a "NativeWindow" with a uniqe window title that the WinForm app can locate.

Dan Byström
  • 9,067
  • 5
  • 38
  • 68
0

For anyone else who finds this here's what I did:

        object addInName = "AddinName";
        var excelApplication = (Microsoft.Office.Interop.Excel.Application)Marshal.GetActiveObject("Excel.Application");
        COMAddIn addIn = excelApplication.COMAddIns.Item(ref addInName);

        addIn.Object.AddinMethodName(params);

Also had to add a reference to Microsoft.Office.Core under COM and Excel.Interop under Assemblies.

Charlie
  • 2,004
  • 6
  • 20
  • 40
0

I assume that your method Foo somehow interacts with Excel. Otherwise you can just add a reference to the assembly containing the class with the Foo method and call it from there without instantiating Excel.

The only other way I can think is to get a reference to your CommandBarButton through the excelApp object. CommandBarButton has a method called Execute which is similar to clicking the button. Something like this:

        Excel.Application excelApp = new Excel.Application(); 
        CommandBarButton btn = excelApp.CommandBars.FindControl(...) as CommandBarButton;
        btn.Execute();
Jakob Christensen
  • 14,826
  • 2
  • 51
  • 81
  • Thanks, that's a neat trick, but I was looking for a more general approach as beyond this simple test application we would have lots of methods, certainly some with parameters and so wouldn't want to create a hidden button for each of them (and how would parameters be handled). – Ben Robbins Feb 13 '09 at 07:58