【问题标题】:VBA call same C++ dll return different resultsVBA 调用相同的 C++ dll 返回不同的结果
【发布时间】:2014-03-10 05:14:31
【问题描述】:

我有一个读取字符串并显示它的测试 dll 函数:

int _stdcall test(LPSTR myString) {
MessageBoxA(NULL, (LPCSTR)myString, "test", MB_OK);
return 0;}

excel VBA声明是

Declare Function test Lib "test.dll" (ByVal text As String) As Long

有一个调用该函数的子程序。它读取值为“abcde”的 excel 单元格,并能够显示正确的结果。子代码是:

sub testCode()
    test (cells(1,1).value)
end sub

但是当使用excel公式=test(A1)调用dll函数时,消息框只显示字符串的第一个字符“a”。

我花了整个周末阅读 BSTR 等,仍然无法解决这个问题。这里发生了什么?

【问题讨论】:

    标签: c++ vba excel dll


    【解决方案1】:

    将您导入的函数声明为私有:

    Private Declare Function test_internal Lib "test.dll" Alias "test" (ByVal text As String) As Long
    

    并创建一个包装函数供 Excel 使用:

    Public Function Test (ByVal text As String) As Long
      Test = test_internal(text)
    End Functin
    

    因为显然,虽然 VB(A) 在调用 Declared API 时使用当前系统代码页将字符串参数转换为 ASCII,但 Excel 引擎不会。

    顺便说一句,您可能还想remove parentheses

    【讨论】:

      【解决方案2】:

      Excel 将 BSTR 传递给您的 C++ 代码。每个字符用 2 个字节编码,第二个字节为 0 表示普通字符。这就解释了为什么您只看到第一个,因为 MessageBoxA 需要 char* 以空字符结尾的字符串。使用

      消息框W

      尝试使用该代码

      int _stdcall test( const wchar_t * pString ) {
         MessageBoxW( NULL, pString, L"test", MB_OK ); // note the L prefix for literral
         return 0;
      }
      

      或者,您可以将 BSTR 指针转换为 char* 指针,使用一些 ATL 宏或原始 Win32 API 作为WideCharToMultiByte(更棘手,使用 ATL 更简单)

      【讨论】:

      • 这是错误的。 VB(A) 在调用Declared API 时根据当前系统代码页将字符串转换为ASCII。唯一不正确的情况是 API 来自类型库。但是,Excel 可能会传递其他内容,但将 Declared 函数直接暴露给 Excel 工作表引擎是我从未想过的事情。
      • @GSerg 你可能是对的,我是 C++ 人,而不是 VBA 人。但是当 xxxA 函数只显示第一个字符时,这是因为传递的指针是 wchar_t*,而不是 char*。
      • 您的回答唯一错误VB pass。将其替换为 Excel pass 会使答案(可能)正确。
      • @GSerg 谢谢,非常感谢。

      • 这是另一个有用的东西:现在函数调用可以以正确的方式显示单词。但是,子现在显示了抓取的特征
        我想把它作为我的周末作业-顺便说一句,有没有什么好的参考书 re excel VBA 和 dll?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多