Expose VSTO functionality to VBA w/o local admin

2019-05-23 01:46发布

What would be the best way to expose certain functionality in a Dotnet VSTO Excel add-in to VBA, without requiring the user to be a local administrator (i.e. no COM registration, no HttpListener)? Would it be possible to use Microsoft Message Queues from VBA?

4条回答
Bombasti
2楼-- · 2019-05-23 02:28

Just for reference for future readers: You might also want to have a look to this question:

Accessing a VSTO application-addin types from VBA (Excel)

and, in particular, to the blog that is referenced there:

VSTO Add-ins, COMAddIns and RequestComAddInAutomationService

By overriding RequestComAddInAutomationService() you can expose whatever functionality you want, by defining a Facade class that provides entry points for all those features, and exposing that class to VBA.

查看更多
聊天终结者
3楼-- · 2019-05-23 02:32

You may be interested in Excel4Net (it is similar to ExcelDNA and ManagedXll, but easier to use):

website: http://www.excel4net.com

blog: http://excel4net.blogspot.com

查看更多
Root(大扎)
4楼-- · 2019-05-23 02:38

If I may interpret your question as broadly as "How do I expose functionality in a .Net assembly to Excel without COM registration" then an excellent solution is to use Excel's XLL interface. Basically one deploys an xll shim and an associated .Net dll. When the xll is loaded it reflects over the dll and exposes the functions therein to Excel.

An open source implementation can be found here http://exceldna.typepad.com/blog/2006/01/introducing_exc.html

A commercial, closed source, but more feature rich one here http://www.managedxll.com/

查看更多
SAY GOODBYE
5楼-- · 2019-05-23 02:49

You can't simply instantiate them as COM objects, as VSTO will not be running in the default application domain.

Here is how I've done it, which is admittedly a bit convoluted. This was with a VSTO workbook saved as an XLA file, which in some ways is more flexible than a pure VSTO add-in.

  • You need to generate a type library using regasm.exe that will be referenced by your VBA code.

  • Create a root factory class in your .NET object model, which is capable of instantiating any of the classes you want to consume in VBA (something like the "Application" class in the Office object models).

  • You then need to find a way to pass a reference to an instance of this factory class to VBA. Once VBA has a reference to an instance of this factory class, it can call its methods to instantiate any other objects in your .NET object model.

  • To pass an instance to VBA, define a macro in your VBA code as follows

Example code:

Private m_objMyFactory As Object

Public Sub RegisterFactory(MyFactory As Object)

    On Error GoTo ErrHandler
    Set m_objMyFactory = MyFactory
    Exit Sub
ErrHandler:
    MsgBox "An unexpected error occurred when registering the Factory component: " & Err.Description
    Exit Sub
End Sub
  • Now add code to the VSTO ThisWorkbook_Open event handler, which instantiates your factory object and calls the above macro passing a reference to the factory object.

Example code:

void ThisWorkbook_Open()
{
     try
     {
         ThisApplication.Run("RegisterFactory",
             new MyNamespace.MyFactory(),
             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);
     }
     catch (Exception ex)
     {
         MessageBox.Show("Load error: " + ex.ToString());
     }
}

There are a few more issues to consider to get this working robustly - if you're interested in following this up let me know and I'll post more details.

查看更多
登录 后发表回答