从VARIANT中提取LPSAFEARRAY

时间:2016-11-16 11:27:29

标签: c++ excel vba

我在C / C ++中编写一个dll,用于从vba中使用,处理双精度数组。在vba中,一个双精度数组内部映射到LPSAFEARRAY结构,这可以传递给C ++。但是也可以在Variant参数中传递它:可以说LPSAFEARRAY包含在Variant参数中。 因为Excel范围也可以在Variant中传递,我编写一个C ++函数,将VARIANT作为参数并生成LPSAFEARRAY,以便在C ++中进一步处理。我的尝试,功能mat(),没有任何检查,是:

VARIANT getdata(VARIANT & ExcelArray) {
    VARIANT dvout;  EXCEPINFO excep; DISPPARAMS dispparams; unsigned int uiArgErr; DISPID dispidValue;
    LPOLESTR XName = L"Value2";
    ExcelArray.pdispVal->GetIDsOfNames(IID_NULL, &XName, 1, LOCALE_SYSTEM_DEFAULT, &dispidValue);
    dispparams.cArgs = 0;
    dispparams.cNamedArgs = 0;
    ExcelArray.pdispVal->Invoke(dispidValue, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dispparams, &dvout, &excep, &uiArgErr);
    ExcelArray.pdispVal->Release();
    return dvout;
}

inline LPSAFEARRAY getarray (VARIANT const &var) {
    // Extract the array (differs if it came in by reference)
    if (var.vt & VT_BYREF)
        return * var.pparray;
    else
        return var.parray;
}

xll_LPSAFEARRAY mat (VARIANT & src) {
    if (src.vt == VT_DISPATCH)      // if range, convert it
        src = getdata(src);
    if (src.vt == VT_R8) {      // a single value
        vbMatrix<double>  A(1, 1);
        A[1] = src.dblVal;
        return A;
    }
    else if ((src.vt & VT_VARIANT) != 0) {
        vbMatrix<VARIANT> v(&src.parray);
        vbMatrix<double>  A(v.rows, v.cols);
        for (int j = 1; j <= v.cols; j++)
            for (int i = 1; i <= v.rows; i++)
                A(i, j) = v(i, j).dblVal;
        return A;
    }
    else {
        LPSAFEARRAY a = getarray(src);
        return a;
    }
}

vba mat中的位置声明为

Declare PtrSafe Function mat Lib "lib.dll" (v) As Double()

现在,范围转换部分正常工作(即通过范围一切都很好)。但最简单的部分,即最后两行,当参数是double数组时调用,只会崩溃Excel。这让我很疯狂,因为底层LPSAFEARRAY的引用必须在Variant中。例如,在vba中,这可以工作:

Dim x() As Double, y() as Double, v as Variant
x = mat([A])    ' array of doubles
v = x           ' out in a Variant
y = v           ' copy to another array of double (= MAKES A COPY)

当然在C ++中也是可能的,但是我需要对原始数组的引用,而不是它的副本。 任何解决方案都表示赞赏。

0 个答案:

没有答案