How can I display the values from this VARIANT instance and save it inside a TStringList?
The COM VARIANT
struct has parray
and pparray
data members that are pointers to a SAFEARRAY
, eg:
VARIANT V;
LPSAFEARRAY sa = V_ISBYREF(&V) ? V_ARRAYREF(&V) : V_ARRAY(&V);
The VCL Variant
class, on the other hand, has an LPSAFEARRAY
conversion operator defined, so you can assign it directly (but only if the Variant.VType
field that not have the varByRef
flag present, that is), eg:
Variant V;
LPSAFEARRAY sa = V;
Either way, once you have the SAFEARRAY
pointer, use the SafeArray API to access the BSTR
values, eg:
bool __fastcall VariantToStrings(const Variant &V, TStrings *List)
{
// make sure the Variant is holding an array
if (!V_ISARRAY(&V)) return false;
// get the array pointer
LPSAFEARRAY sa = V_ISBYREF(&V) ? V_ARRAYREF(&V) : V_ARRAY(&V);
// make sure the array is holding BSTR values
VARTYPE vt;
if (FAILED(SafeArrayGetVartype(sa, &vt))) return false;
if (vt != VT_BSTR) return false;
// make sure the array has only 1 dimension
if (SafeArrayGetDim(sa) != 1) return false;
// get the bounds of the array's sole dimension
LONG lBound = -1, uBound = -1;
if (FAILED(SafeArrayGetLBound(sa, 0, &lBound))) return false;
if (FAILED(SafeArrayGetUBound(sa, 0, &uBound))) return false;
if ((lBound > -1) && (uBound > -1))
{
// access the raw data of the array
BSTR *values = NULL;
if (FAILED(SafeArrayAccessData(sa, (void**)&values))) return false;
try
{
List->BeginUpdate();
try
{
// loop through the array adding the elements to the list
for (LONG idx = lBound; l <= uBound; ++idx)
{
String s;
if (values[idx] != NULL)
s = String(values[idx], SysStringLen(values[idx]));
List->Add(s);
}
}
__finally
{
List->EndUpdate();
}
}
__finally
{
// unaccess the raw data of the array
SafeArrayUnaccessData(sa);
}
}
return true;
}
VarClear(V);
TVarData(V).VType = varOleStr;
You don't need those at all. The VCL Variant
class initializes itself to a blank state, and there is no need to assign the VType
since you are assigning a new value to the entire Variant
immediately afterwards.
V = ComFunction->GetValues(); //<<<<----- V is empty
If V is empty, then GetValues()
is returning an empty Variant
to begin with.
mystr = (wchar_t *)(TVarData(V).VString);
TVarData::VString
is an AnsiString&
reference, not a wchar_t*
pointer. To convert a VCL Variant
(not a COM VARIANT
) to a String
, just assign it as-is and let the RTL works out the detail for you:
String mystr = V;