//------------------------------------------------------------------- void cpp_xloper::operator=(VARIANT *pv) { Free(); if(vt_to_xloper(m_Op, pv, false) && m_Op.xltype == xltypeStr) m_DLLtoFree = true; }
//------------------------------------------------------------------- // The Variant constructor. Takes type from the VARTYPE. //------------------------------------------------------------------- cpp_xloper::cpp_xloper(VARIANT *pv) { Clear(); if(vt_to_xloper(m_Op, pv, true) && (m_Op.xltype == xltypeStr || m_Op.xltype == xltypeMulti)) m_DLLtoFree = true; }
//------------------------------------------------------------------- // Converts the passed-in array Variant to an xltypeMulti xloper. //------------------------------------------------------------------- bool array_vt_to_xloper(xloper &op, const VARIANT *pv) { if(!pv || !pv->parray) return false; int ndims = pv->parray->cDims; if(ndims == 0 || ndims > 2) return false; int dims[2] = {1,1}; long ubound[2], lbound[2]; for(int d = 0; d < ndims; d++) { // Dimension argument counts from 1, so need to pass d + 1 if(FAILED(SafeArrayGetUBound(pv->parray, d + 1, ubound + d)) || FAILED(SafeArrayGetLBound(pv->parray, d + 1, lbound + d))) return false; dims[d] = (short)(ubound[d] - lbound[d] + 1); } op.val.array.lparray = (xloper *)malloc(dims[0] * dims[1] * XLOPER_SIZE); if(!op.val.array.lparray) return false; op.val.array.rows = dims[0]; op.val.array.columns = dims[1]; op.xltype = xltypeMulti; xloper *p_op = op.val.array.lparray; // Use this union structure to retrieve elements of the SafeArray union { VARIANT var; short I2; double R8; ULONG ulVal; CY cyVal; bool boolVal; BSTR bstrVal; } temp_union; xloper temp_op; VARTYPE vt_type = pv->vt & ~VT_ARRAY; long element_index[2]; void *vp; SafeArrayAccessData(pv->parray, &vp); SafeArrayUnaccessData(pv->parray); for(WORD r = 0; r < dims[0]; r++) { for(WORD c = 0; c < dims[1];) { element_index[0] = r + lbound[0]; element_index[1] = c++ + lbound[1]; if(FAILED(SafeArrayGetElement(pv->parray, element_index, &temp_union))) { temp_op.xltype = xltypeNil; } else { switch(vt_type) { case VT_I2: temp_op.xltype = xltypeInt; temp_op.val.w = temp_union.I2; break; case VT_R8: temp_op.xltype = xltypeNum; temp_op.val.num = temp_union.R8; break; case VT_BOOL: temp_op.xltype = xltypeBool; temp_op.val.xbool = temp_union.boolVal; break; case VT_VARIANT: // Don't allow Variant to contain an array Variant to prevent recursion if(vt_to_xloper(temp_op, &temp_union.var, false)) break; case VT_ERROR: temp_op.xltype = xltypeErr; temp_op.val.err = (unsigned short)(temp_union.ulVal - VT_XL_ERR_OFFSET); break; case VT_CY: temp_op.xltype = xltypeNum; temp_op.val.num = (double)(temp_union.cyVal.int64 / 1e4); break; case VT_BSTR: op.xltype = xltypeStr; op.val.str = vt_bstr_to_xlstring(temp_union.bstrVal); break; default: temp_op.xltype = xltypeNil; } } *p_op++ = temp_op; } } return true; }