使用在C ++中创建的DLL从Excel和VBA调用C ++函数

时间:2013-10-06 21:32:48

标签: c++ excel vba excel-vba dll

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

koduj需要两个参数:string nr_idinteger x1。它以ASCII表示形式计算nr_id个字母的总和,并添加x1。计算的总和不是。

我按照发现的here说明。

这是我的.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 个答案:

答案 0 :(得分:2)

原因是即使VBA字符串是内部UTF-16,VB在与外界交谈之前总是将它们转换为ASCII(Declare d函数,文件输入/输出)。因此,当您Declare参数As String时,VBA automatically converts将字符串作为ASCII传递出去。 C ++端的匹配参数类型应为LPSTRLPCSTR

如果要在C ++端使用BSTR,还需要为该函数创建一个IDL文件,将其编译为TLB并从VBA引用TLB,然后VBA才会尊重并使用{ {1}}。

另一个问题是C ++的BSTR转换为VBA的int

从Excel工作表调用时它的工作原理显然是Excel ignores the VBA rules for string conversion。我相信这是一个错误。

答案 1 :(得分:0)

尝试声明a长: 昏昏欲睡

答案 2 :(得分:0)

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

http://msdn.microsoft.com/en-us/library/office/bb687915(v=office.15).aspx上有一篇关于所有这些内容的微软文章。

答案 3 :(得分: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)