如何公开要从 VBA 调用的 C# XLL 方法?

How do I expose a C# XLL method to be called from VBA?

提问人:RobBaker 提问时间:11/7/2023 最后编辑:RobBaker 更新时间:11/8/2023 访问量:45

问:

我在这里看过类似的答案,但没有一个能完全回答我的问题。

我有一个 C# XLL,其中包含一个 UDF(由 ExcelDNA 提供支持)和一些帮助程序类和方法 - 其中之一是:

namespace Data_Tool
{
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    public class DataCache
    {
        public static Dictionary<string, DataCache> calcs = new Dictionary<string, DataCache> { };
        
        string filepath;
        object[,] data;

        // Class constructor
        public DataCache(string filepath)
        {
            this.filepath = filepath;
            this.data = new object[,] { };
        }
        
        public static void RemoveCache(string filename)
        { // This allows an external entity to call and remove cached data for a particular file
            if (calcs.ContainsKey(filename)) calcs.Remove(filename);
        }
    }
}

我试图做的是在 Excel VBA 中使用事件处理程序(BeforeClose 事件)来触发上面的最后一个方法 (RemoveCache) - 目的是在文件关闭时从“calcs”字典中删除缓存的项目。 我的VBA代码尝试像这样映射XLL函数,但是在尝试执行时,我总是收到入口点未找到错误:

#If Win64 Then
    Declare PtrSafe Sub RemoveCache Lib "DataTool-AddIn64.xll" (filename As String)
#Else
    Declare PtrSafe Sub RemoveCache Lib "DataTool-AddIn.xll" (filename As String)
#End If

Public Sub test()
    RemoveCache ThisWorkbook.FullName
End Sub

您将看到,在我的 C# 幼稚中,我尝试使用 ComVisible 向 COM 公开 RemoveCache 方法 - 但显然这是不正确的。我不太确定如何更改我的代码以使 RemoveCache 可从 VBA 调用。

C# Excel VBA

评论

0赞 Charlieface 11/8/2023
将 C# DLL 添加为 COM 引用
0赞 RobBaker 11/9/2023
由于工作簿的构建方式的体系结构原因,这不是一个实用的解决方案,但绝对适用于测试设置。原因是用户从加载项自行创建这些启用宏的工作簿,但并非每个需要查看文件(例如用于检查)的人都会安装加载项,即如果文件中定义了引用,但他们的计算机上缺少引用,他们将出现可怕的 VBA 错误。

答:

0赞 RobBaker 11/8/2023 #1

我发现了一个有点笨拙的解决方案 - 因为我已经在使用 ExcelDNA 在同一个 XLL 中生成一些 UDF,我刚刚制作了一个名为 RemoveCache 的 void 函数来执行相同的操作 - 或者实际上只是为我调用 C# 中的方法。这允许我使用 Application.Run 在 VBA 中调用该函数:

Private Sub Workbook_BeforeClose(Cancel As Boolean)
    On Error Resume Next ' Set to skip if the DataTool add-in is not present
    Application.Run "RemoveCache", ThisWorkbook.FullName
End Sub

那么我在 C# 中的 UDF 代码是:

[ExcelFunction(Description = "Erase cache item", IsMacroType = true)]
public static void RemoveCache(string filename)
{
    DataCache.RemoveCacheItem(filename);
}

其中 RemoveCacheItem 是我原始问题的 DataCache 类中的重命名方法。

使用这种方法有什么陷阱吗,因为它很简单,所以我喜欢它?