在EXCEL VBA中使用C#dll

Joh*_*nyy 12 c# dll vba

我在这里遇到一个小问题,需要你帮忙.

我有一个通过COM互操作公开的C#DLL.它工作正常,但显然C#interop对象的部署是一场灾难,每次更新DLL时都需要重新计算.

所以我想知道如何使用这个C#DLL中的函数,如下所示:或者我可以通过将DLL和电子表格放在一起来调用函数.

Declare Function getString Lib "<PATH of my DLL>" () as string

sub test()
   range("A1").value = getString
End Sub
Run Code Online (Sandbox Code Playgroud)

语法可能有误.

Rob*_*cke 16

你可以这样做,但你必须意识到VBA和.Net的区别.
首先,您必须创建一个实际的DLL(.Net程序集不是),为此,使用此项目模板.然后,你必须知道如何编组东西.
VBA仅支持stdcall作为调用约定,它不能真正处理DLL函数的Unicode.这本身并不错,因为.Net中String的默认封送是VBA所期望的(指向Ansi char的指针).此外,stdcall是我用于导出的默认调用约定.

我将重用我最近为另一个SO线程创建的示例:

把它放在你使用我的模板创建的项目中:

[ComVisible(true), ClassInterface(ClassInterfaceType.AutoDual)]
public class Sample
{
   public string Text
   {
      [return: MarshalAs(UnmanagedType.BStr)]
      get;
      [param: MarshalAs(UnmanagedType.BStr)]
      set;
   }

   [return: MarshalAs(UnmanagedType.BStr)]
   public string TestMethod()
   {
      return Text + "...";
   }
}

static class UnmanagedExports
{
   [DllExport]
   [return: MarshalAs(UnmanagedType.IDispatch)]
   static Object CreateDotNetObject(String text)
   {
      return new Sample { Text = text };
   }
}
Run Code Online (Sandbox Code Playgroud)

这是如何从VBA调用它:

Declare Function CreateDotNetObject Lib "The full path to your assembly or just the assembly if it is accessible from Excel" _
  (ByVal text As String) As Object

Sub test()

  Dim instance As Object

  Set instance = CreateDotNetObject("Test 1")
  Debug.Print instance.Text

  Debug.Print instance.TestMethod

  instance.text = "abc 123" ' case insensitivity in VBA works as expected'

  Debug.Print instance.Text
End Sub
Run Code Online (Sandbox Code Playgroud)