在 Excel VBA 中使用来自 COM 插件的 CLR 类?

Use CLR classes from COM addin in Excel VBA?

我有一个 Excel VSTO COM 插件,我可以在 Excel VBA 中成功加载引用。我可以交换基本类型(如字符串),但我也可以在 VBA 中使用我的插件中的复杂 classes 吗?

假设我在 C# 中有这个 class:

public class TestClass {
    public string GetTextFunc() => "check";
    public string TextProp => "doublecheck";
    public int RollDice() => 4; // chosen by fair dice roll
}

...我的插件提供了这个 class 到 Excel 的对象:

[ComVisible(true)]
public interface IUtilities {
    string GetString();
    TestClass GetTestClass();
}

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class Utilities: IUtilities {
    public string GetString() => "Hello Excel";
    public TestClass GetTestClass() => new TestClass();
}

所以一切都是默认的 VSTO 教程内容,除了 class。

现在,当我在 Excel VBA 块(例如在“ThisWorksheet”)中使用我的插件时,通过定义这样的函数:

Sub TestAddin()
    Dim addIn As COMAddIn
    Dim automationObject As Object
    Set addIn = Application.COMAddIns("MyExcelAddin")
    Set automationObject = addIn.Object
    
    ActiveSheet.Range("A1").Value2 = automationObject.GetString()
    
    Dim tc
    Set tc = automationObject.GetTestClass()
    ActiveSheet.Range("A2").Value2 = tc.GetTextFunc()
End Sub

...然后 A1 被正确设置,正如预期的那样,我可以一直调试到最后一行(因此获取 tc 的对象仍然有效!),但在最后行我得到一个错误“需要对象”。我可以看到 tcVariant/Object 类型,所以我假设 VBA 只是不知道如何处理它。有什么办法

  1. 告诉 VBA 这个 class 长什么样子
  2. 实际上它可以工作,所以在 VBA 中调用 tc 上的函数会调用我的 .Net 库中的正确代码?

TestClass class 必须像您的实用程序一样实现 class - 它必须实现 public IDispatch 派生接口。

[ComVisible(true)]
public interface ITestClass {
    string GetTextFunc();
    string TextProp ();
    int RollDice();
}

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class TestClass : ITestClass {
    public string GetTextFunc() => "check";
    public string TextProp => "doublecheck";
    public int RollDice() => 4;
}

现在 VBA 调用有一个 Class 方法接口,例如 GetTextFunc:

Dim tc
Set tc = automationObject.GetTestClass()
ActiveSheet.Range("A2").Value2 = tc.GetTextFunc()