从 C# 访问 VBA 函数

Posted

技术标签:

【中文标题】从 C# 访问 VBA 函数【英文标题】:Access VBA functions from C# 【发布时间】:2014-07-29 09:50:26 【问题描述】:

我目前正在玩活动。但不幸的是,VBA 中的后期绑定不支持事件。所以我正在使用AddressOf。在 Access/Excel(我的应用程序)中它工作正常 (see link)

从 C# 调用文本返回“??”而不是正确的文本

谢谢,安迪

    public delegate void CallbackMsg(string msg, int unused1, int unused2, int unused3);

    [ComVisible(true)]
    public void TestProcess(int callback)
    

        CallbackMsg x = (CallbackMsg)Marshal.GetDelegateForFunctionPointer(new IntPtr(callback), typeof(CallbackMsg));
        x.Invoke("Hello Office", 0, 0, 0);

        System.Windows.Forms.MessageBox.Show("Test DOTNET");
    

【问题讨论】:

这是一个猜测,但它可能与 unicode 相关吗? C# 文本将是 unicode,但 Access(或您使用的函数)可能不是。 当我在 VBA 中移动变量时,工具提示显示“ 这确实向我表明您遇到了编码问题。 Unicode 可以是每个字符 2 个字节。 【参考方案1】:

VB 内部使用的字符串既不是 C 风格的以空字符结尾的字符串,也不是“标准”Unicode 字符串。它们是一种名为 BSTR(基本字符串)的特殊结构。

C# 有一种通过 Marshal 类处理它们的方法,因此 C# 代码将如下所示:

public delegate void CallbackMsg(IntPtr bstrMsg, int unused1, int unused2, int unused3);

[ComVisible(true)]
public void TestProcess(int callback)

   IntPtr ptrBSTR = Marshal.StringToBSTR("Hello Office");
   CallbackMsg x = (CallbackMsg)Marshal.GetDelegateForFunctionPointer(new IntPtr(callback), typeof(CallbackMsg));
   x.Invoke(ptrBSTR, 2, 4, 6);
   Marshal.FreeBSTR(ptrBSTR); //MUST free it

我用 Excel 2010 对此进行了测试,但我认为它与其他 VBA 产品相同。 VBA 代码如下所示:

Public Sub CallbackMsg(ByVal s As String, ByVal unused1 As Long, ByVal unused2 As Long, ByVal unused3 As Long)
   Debug.Print "This string came from C#: "; s
   Debug.Print unused1, unused2, unused3
End Sub

Sub TestComVisbl()
   Dim o As Object
   Set o = CreateObject("ComVisbl.Class1")
   Call o.TestProcess(AddressOf CallbackMsg)
End Sub

【讨论】:

以上是关于从 C# 访问 VBA 函数的主要内容,如果未能解决你的问题,请参考以下文章

从 Excel 调用的访问 vba 函数导致返回不同的值

从 Java 调用 Access 中的 VBA 函数

在 Excel VBA 中使用 C# 库函数

在 VBA 中访问选择组合框列返回“函数未定义”-错误

从 Excel 调用 Access VBA 函数

从 C# 程序访问 C++ DLL 中的多个函数