Quantcast
Channel: Active questions tagged excel - Stack Overflow
Viewing all articles
Browse latest Browse all 88030

C++ DLL, return VARIANT (SafeArray of BSTR) to VBA has Run Time Error 10: This array is fixed or temporarily locked

$
0
0

I have this problem for a long time, any help would be very appreciated! I am writing a C++ DLL used in VBA. While when I try to return a VARIANT (contain a SafeArry of BSTR) back to VBA and using this return value to fill the cells in excel, the cells are filled with correct values but I have Run-time error 10: This array is fixed or temporarily locked.

The idea is to pass a 2d matrix from excel to DLL to do some filtration and then pass the result back to Excel. As ScreenShot below, here I want to only keep people with "Active" Status:

enter image description here

I am wondering do I need to destroy the variant (varOut in my code)? how should I do that?

Or I have wrong declaration in VBA? What puzzled me is I can still fill right values to the cells in Excel but in the meantime, I have the run-time error.

My VBA Definition is as follow:

Declare Function PrepareData Lib "C:\dll_path" (source As Variant) As Variant 

Sub test()
  Dim input, result As Range
  Set input = Range("A1:C4")
  Set result = Range("A6:C6")
  result.value = PrepareData(input.value)

And my C++ Code is as below:

VARIANT __stdcall PrepareData(VARIANT* sourceRange) {
// Convert VBA Range to 2d Vector
vector<vector<string>> sourceArray = VBARangeToArray(sourceRange);

// Do filteration
vector<vector<string>> outputArray = FilterData(sourceArray);

// Convert 2d Vector back to VBA Variant
VARIANT outputRange = ArrayToVBARange(outputArray);

return outputRange;}

VARIANT ArrayToVBARange(vector<vector<string>> Array) {
int nrows = Array.size();
int ncols = Array[0].size();
int cnt_elements = nrows * ncols;

// Construct new SafeArray
BSTR *ptrArray = NULL;
SAFEARRAYBOUND rgsabound[2];
rgsabound[0].lLbound = 1;
rgsabound[0].cElements = nrows;
rgsabound[1].lLbound = 1;
rgsabound[1].cElements = ncols;

SAFEARRAY* pStringArray = SafeArrayCreate(VT_BSTR, 2, rgsabound);

HRESULT hr = SafeArrayAccessData(pStringArray, (void**)&ptrArray);

// Fill the SafeArray
for (int i = 0; i < cnt_elements; i++) {
    int Row = i % nrows;
    int Col = i / nrows;
    _bstr_t tmp(Array[Row][Col].c_str());
    ptrArray[i] = tmp.copy();
}
SafeArrayUnaccessData(pStringArray);

// Constrcut the return variable, type: Variant
VARIANT varOut;
VariantInit(&varOut);
varOut.vt = VT_ARRAY | VT_BSTR;
varOut.parray = pStringArray;
return varOut;}

Viewing all articles
Browse latest Browse all 88030

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>