S
squillion
hello
how do i use the C API to get at the contents of a multi-part range?
more specifically how to i run xlCoerce on a reference xRef where
xRef->val.mref.lpmref->count > 1 ?
consider the function below which takes a range as the sole input
parameter, and for each cell in that range writes the cell's contents
to a logfile:
__declspec(dllexport) int WINAPI getRange(LPXLOPER xRef) {
//omitted - set up logfile log1 and try/catch
XLOPER xGet, xDestType;
xDestType.xltype = xltypeNum;
xDestType.val.num = xltypeMulti;
if (xlretSuccess != Excel(xlCoerce, &xGet, 2, xRef, &xDestType)) {
throw exception("unable to coerce input range");
}
for (int i = 0; i < xGet.val.array.rows * xGet.val.array.columns;
i++) {
// assume all the cells contain xltypeNums
log1 << i << " - " << xGet.val.array.lparray.val.num << endl;
}
}
the above function works as i expect when i call it from VBA and pass
a single-part range as the parameter:
ret = Application.Run("getRange", Range("A1:C2"))
but of course the function prints out gibberish if i pass it a
multi-part range:
ret = Application.Run("getRange", Range("A1:C2,A4:B5"))
how do i handle the second case? the best i've come up with so far is
to create a local reference to a one-part range, and copy the contents
of the multi-part range into the one-part range one chunk at a time:
__declspec(dllexport) int WINAPI getRange(LPXLOPER xRef) {
XLOPER xRefCopy, xGet, xDestType;
xRefCopy.xltype = xltypeRef;
xRefCopy.val.mref.idSheet = xRef->val.mref.idSheet;
xRefCopy.val.mref.lpmref = new XLMREF [ 1 ];
xRefCopy.val.mref.lpmref->count = 1;
xDestType.xltype = xltypeNum;
xDestType.val.num = xltypeMulti;
for (int i = 0; i < xRef->val.mref.lpmref->count; i++) {
log1 << i << " ***" << endl;
xRefCopy.val.mref.lpmref->reftbl[0].rwFirst
= xRef->val.mref.lpmref->reftbl.rwFirst;
xRefCopy.val.mref.lpmref->reftbl[0].rwLast
= xRef->val.mref.lpmref->reftbl.rwLast;
xRefCopy.val.mref.lpmref->reftbl[0].colFirst
= xRef->val.mref.lpmref->reftbl.colFirst;
xRefCopy.val.mref.lpmref->reftbl[0].colLast
= xRef->val.mref.lpmref->reftbl.colLast;
if (xlretSuccess != Excel(xlCoerce, &xGet, 2, &xRefCopy,
&xDestType)) {
throw exception("unable to coerce input range");
}
for (int j = 0; j < xGet.val.array.rows * xGet.val.array.columns;
j++) {
log1 << j << " - " << xGet.val.array.lparray[j].val.num << endl;
}
}
}
that does what i want, but surely there's a better way.
TIA
eric
how do i use the C API to get at the contents of a multi-part range?
more specifically how to i run xlCoerce on a reference xRef where
xRef->val.mref.lpmref->count > 1 ?
consider the function below which takes a range as the sole input
parameter, and for each cell in that range writes the cell's contents
to a logfile:
__declspec(dllexport) int WINAPI getRange(LPXLOPER xRef) {
//omitted - set up logfile log1 and try/catch
XLOPER xGet, xDestType;
xDestType.xltype = xltypeNum;
xDestType.val.num = xltypeMulti;
if (xlretSuccess != Excel(xlCoerce, &xGet, 2, xRef, &xDestType)) {
throw exception("unable to coerce input range");
}
for (int i = 0; i < xGet.val.array.rows * xGet.val.array.columns;
i++) {
// assume all the cells contain xltypeNums
log1 << i << " - " << xGet.val.array.lparray.val.num << endl;
}
}
the above function works as i expect when i call it from VBA and pass
a single-part range as the parameter:
ret = Application.Run("getRange", Range("A1:C2"))
but of course the function prints out gibberish if i pass it a
multi-part range:
ret = Application.Run("getRange", Range("A1:C2,A4:B5"))
how do i handle the second case? the best i've come up with so far is
to create a local reference to a one-part range, and copy the contents
of the multi-part range into the one-part range one chunk at a time:
__declspec(dllexport) int WINAPI getRange(LPXLOPER xRef) {
XLOPER xRefCopy, xGet, xDestType;
xRefCopy.xltype = xltypeRef;
xRefCopy.val.mref.idSheet = xRef->val.mref.idSheet;
xRefCopy.val.mref.lpmref = new XLMREF [ 1 ];
xRefCopy.val.mref.lpmref->count = 1;
xDestType.xltype = xltypeNum;
xDestType.val.num = xltypeMulti;
for (int i = 0; i < xRef->val.mref.lpmref->count; i++) {
log1 << i << " ***" << endl;
xRefCopy.val.mref.lpmref->reftbl[0].rwFirst
= xRef->val.mref.lpmref->reftbl.rwFirst;
xRefCopy.val.mref.lpmref->reftbl[0].rwLast
= xRef->val.mref.lpmref->reftbl.rwLast;
xRefCopy.val.mref.lpmref->reftbl[0].colFirst
= xRef->val.mref.lpmref->reftbl.colFirst;
xRefCopy.val.mref.lpmref->reftbl[0].colLast
= xRef->val.mref.lpmref->reftbl.colLast;
if (xlretSuccess != Excel(xlCoerce, &xGet, 2, &xRefCopy,
&xDestType)) {
throw exception("unable to coerce input range");
}
for (int j = 0; j < xGet.val.array.rows * xGet.val.array.columns;
j++) {
log1 << j << " - " << xGet.val.array.lparray[j].val.num << endl;
}
}
}
that does what i want, but surely there's a better way.
TIA
eric