2017-11-27 3 views
2

VBAから呼び出されるとC++ DLLが作成され、SAFEARRAY *が返されます。Stringのバリアント配列に代替スペースが含まれています

私のVBA関数:

Declare Function GetData_V Lib "xyz.dll" (ByVal path As String, ByVal id As String, ByRef inputArr() As String, ByRef output() As String) As Variant() 

私のC++の実装:

SafeArrayLock(*outputArray); 
    for (LONG i = 0; i < countElements; i++) 
    { 
     CComBSTR bstr = CComBSTR(outputCustom[i]); 
     SafeArrayPutElement(*outputArray, &i, bstr); 
    } 
    SafeArrayUnlock(*outputArray); 

    delete [] outputCustom; 

    return *outputArray; 

私はそれのように文字列を示し、出力を確認したときにoutputCustomはVBAで

outputCustom = new char*[nCount+1]; 

のように定義されます。

1 0 . 9 4 4 9 d 0 
2 . 8 3 4 6 d 0 
0 . 0 1 1 8 d 0 
0 . 6 2 9 9 d 0 
0 . 6 2 9 9 d 0 
0 . 6 2 9 9 d 0 
2 5 . 0 d 0 
0 . 0 7 6 4 d 0 
1 0 . 9 4 4 9 d 0 
2 . 8 3 4 6 d 0 
0 . 0 1 1 8 d 0 

私はコードをデバッグし、C++で* outputArrayの値をチェックしましたが、すべて正常ですが、VBAで配列をチェックすると、各文字列の各文字の間に余分なスペースがあります。

+0

私は同じことをしている人のブログを見ています - 結論は 'AA'の答えによるものですhttps://www.daniweb.com/programming/software-development/threads/271964/returning-array-of -string-from-c-dll-to-vba – UKMonkey

答えて

2

VB6と同様、VBAはUnicode(ワイド文字)文字列を必要とします。

How to: Access DLLs in Excel -- Variant and String Arguments

Excelは、ワイド文字Unicode文字列を内部的に動作します。 VBAユーザー定義関数がString引数をとると宣言されると、Excelは指定された文字列をロケール固有の方法でバイト列に変換します。関数にUnicode文字列を渡す場合は、VBAユーザー定義関数は文字列引数の代わりにVariantを受け入れる必要があります。 DLL関数は、VBAからVariant BSTRワイド文字列を受け入れることができます。

表示されるスペースは、16ビットの文字のゼロバイトの上位バイトです。文字列をCComBSTRのコンストラクタに渡す前に、wchar_tを使用するか、widecharに変換する必要があります。 MultiByteToWideCharmbstowcs、またはATL and MFC String Conversion Macrosを使用して、この操作を行うことができます。

VBAがVBからあなたのDLLにそのようなオブジェクトを渡してそこで検査することを期待するのは良いヒントです。

Eric’s Complete Guide To BSTR Semanticsもおもしろいです。

関連する問題