3

C APIを使用して、Excel用の配列コンストラクターをワークシート関数として記述しようとしています。

ゴール:=array_cons(1, 2, 3) => {1, 2, 3}

ただし、XLOPER12を正しく初期化できていません。Excelでは、私の関数は現在。を返します#NUMvargs引数リストを取得し、マクロを介して配列にパックしてから、提供された配列の一部を返そうとしています。

#include <windows.h>
#include <xlcall.h>
#include <framewrk.h>
#include <boost/preprocessor.hpp>

#define VARG_COUNT 250
#define VARG_FORMAT(Z, A, B) B##A, 
#define VARG_DEF_LIST(N) BOOST_PP_REPEAT(N, VARG_FORMAT, LPXLOPER12 varg) \
                         LPXLOPER12 varg##N
#define VARG_ARRAY(N) { BOOST_PP_REPEAT(N, VARG_FORMAT, varg) varg##N }
#define GET_VARGS VARG_ARRAY(VARG_COUNT)

__declspec(dllexport) LPXLOPER12 WINAPI array_cons(VARG_DEF_LIST(VARG_COUNT))
{
    LPXLOPER12 vargs[] = GET_VARGS;
    int args_passed = 0;
    for(int i = 0; i < VARG_COUNT; ++i, ++args_passed)
    {
        if (vargs[i]->xltype == xltypeMissing)
        {
            break;
        }
    }
    if (args_passed == 0)
    {
        XLOPER12 err;
        err.xltype = xltypeErr;
        err.val.err = xlerrValue;
        return (LPXLOPER12)&err;
    }
    XLOPER12 list;
    list.xltype = xltypeMulti;
    list.val.array.lparray = (XLOPER12*)vargs;
    list.val.array.rows = args_passed;
    list.val.array.columns = 1;
    return (LPXLOPER12)&list;
}
4

3 に答える 3

2

私はそれを考え出した。ここで注意すべき点がいくつかあります-

UDF登録が正しい署名を使用していることを確認する必要があります。私の場合、Excel参照でそれぞれの値を取得したかったのでQ、関数を登録するときに型を使用しました。これがわからない場合は、http://msdn.microsoft.com/en-us/library/office/bb687869.aspxを確認してください。

配列を返すには、新しいメモリをメンバーに動的に割り当ててlist.val.array.lparray、繰り返しデータを入力する必要があります。

__declspec(dllexport) LPXLOPER12 WINAPI array_cons(VARG_DEF_LIST(VARG_MAX)) {
    LPXLOPER12 vargs[] = GET_VARGS;
    int args_passed = 0;
    for(int i = 0; i < VARG_MAX; ++i, ++args_passed) {
        if (vargs[i]->xltype == xltypeMissing) {
            break;
        }
    }
    XLOPER12 list;
    list.xltype = xltypeMulti | xlbitDLLFree;
    list.val.array.lparray = new XLOPER12[args_passed];
    list.val.array.rows = args_passed;
    list.val.array.columns = 1;
    for(int i = 0; i < args_passed; ++i) {
        list.val.array.lparray[i] = *vargs[i];
    }
    return &list;
}

メモリを動的に割り当てているため、メモリを解放するためにコールバックを定義する必要があります。

__declspec(dllexport) void WINAPI xlAutoFree12(LPXLOPER12 p) {
    if (p->xltype == (xltypeMulti | xlbitDLLFree)) {
        delete [] p->val.array.lparray;
    }
}
于 2013-01-19T19:22:03.997 に答える
1

あなたの解決策は不完全です。

あなたが書く

XLOPER12 list;

関数の本体にあります。これにより、「リスト」はスタック上に作成されるローカル変数になります。関数が戻ると、「list」はスコープ外になります。スコープ内にない変数へのポインターを返していますが、Excelがこのポインターにアクセスしようとすると、動作は未定義になります。戻り値を処理する前にExcelがたまたま別の関数を呼び出すと、リスト変数が破壊されます。

解決策は、リストにメモリを動的に割り当てる(そして、後で確実に解放されるようにする)か、リストを静的変数またはグローバル変数にする必要があることです。

于 2013-11-07T16:35:39.540 に答える
0

xllライブラリでオープンソースのアドインを開発できないと思う理由がわかりません。IANALですが、Ms-PLはそれを許可しているようです。http://xllfunctional.codeplex.com/を見たことがありますか?ブーストをソリューションに引きずり込まない、同様の移植性のないトリックを使用します。WINAPI/__stdcallはそれが何であるかです。シリコンに至るまでの状況を知っていれば、それを利用できます。

于 2013-02-25T02:38:38.197 に答える