9

我创建了一个包含名为“koduj”的函数的 DLL。通过在 Excel 工作表单元格中使用此函数来调用它会返回所需的结果。从 VBA 调用“koduj”返回错误答案。

koduj 需要两个参数:string nr_idinteger x1. 它以 ASCII 表示形式计算nr_id' 字母的总和并添加x1. 计算的总和比返回。

我按照此处找到的说明进行操作。

这是我的 .cpp 源文件:

#include<Windows.h>
#include<string>
using namespace std;


//Convert BSTR to wstring for convenience
wstring BSTR_to_wstring (BSTR text){
    return wstring(text, SysStringLen(text));
}

//Calculate sum of letters in ASCII representation
int ASCII_sum (wstring ws){
    int sum = 0;
    for (unsigned int i = 0; i < ws.length(); i++)
        sum += ws[i];
    return sum;
}

//"koduj" function
int _stdcall koduj (BSTR nr_id, int & x1){
    wstring ws_nr_id = BSTR_to_wstring(nr_id);
    return ASCII_sum(ws_nr_id) + x1;
}

这是我的 VBA 函数声明:

Declare Function koduj _
Lib "<dll_directory_and_full_name>" (ByVal x As String, ByRef y As Integer) As Integer

通过写作:

=koduj("aaa";1)

在工作表单元格内,我得到了想要的结果 (292)

调试此 VBA 代码:

Sub test()

Dim a As Integer
a = koduj("aaa", 1)

End Sub

显示错误结果 (a = 24930)

我相信我的 C++ 代码很好,因为它在从 Excel 的工作表中调用时可以正常工作。

4

4 回答 4

3

The reason is that even though VBA strings are internally UTF-16, VB always converts them to ASCII before talking to the outside world (Declared functions, file input/output). So when you Declare a parameter As String, VBA automatically converts the string and passes it out as ASCII. The matching parameter type on the C++ side should be LPSTR or LPCSTR.

If you want to use BSTR on the C++ side, you need to also create an IDL file for that function, compile it into a TLB and reference the TLB from VBA, only then VBA will respect and use BSTR.

Another problem is that C++'s int translates to VBA's Long.

The reason why it works when called from Excel sheet is that apparently Excel ignores the VBA rules for string conversion. I believe this to be a bug.

于 2017-06-06T18:58:24.833 回答
0

尝试声明 a as long:Dim a As Long

于 2014-03-10T12:08:17.400 回答
0

我从错误的大小猜测它是错误的数字参数 - 我会尝试更明确地在您的测试 VBA 例程中声明参数类型(可能是整数)并接受它作为 C++ 端的特定类型(签名简而言之,在这种情况下)。

在http://msdn.microsoft.com/en-us/library/office/bb687915(v=office.15).aspx上有一篇很棒的 Microsoft 文章。

于 2014-04-18T17:17:11.880 回答
0

不打算成为一个完整的答案,但您的第二个参数的类型看起来错误。

您的 DLL 函数: int _stdcall koduj (BSTR nr_id, int & x1) 声明x1为对(大概)32 位整数的引用。

您的 VBA 声明: 将Declare Function koduj Lib "<dll_directory_and_full_name>" (ByVal x As String, ByRef y As Integer) As Integer y 声明为指向16 位整数的指针。

我建议尝试如下更改 VBA 声明:

Declare Function koduj _ Lib "<dll_directory_and_full_name>" (ByVal x As String, ByVal y As Long) As Long

并且,切换您的 DLL 函数签名以按值传递 x1:

int _stdcall koduj (BSTR nr_id, int x1)

于 2017-02-06T20:22:47.143 回答