View Single Post
  #1   Report Post  
Posted to microsoft.public.excel.programming
Henry[_7_] Henry[_7_] is offline
external usenet poster
 
Posts: 3
Default Retrieve Excel Cell Range into SAFEARRAY (VC++)

Hi all,

I am very new to Excel Programming and COM/Automation so please forgive
any amateur or foolish questions.

I am trying to extract the values of a range cells from a workbook. I
have successfully opened the workbook and can iterate the worksheets. I
have been able to extract the value of a single cell but to iterate
through all the cells in a workbook is not an option as this is quite
resource intensive. So, I assume there is a way I can load a range of
cells into a SAFEARRAY. The SAFEARRAY being held in a VARIANT.

This is the code that I have (error checking is only displayed where it
failed but I am checking all return values):

#import "C:\Program Files\Microsoft Office\Office\MSO9.DLL"
#import "C:\Program Files\Common Files\Microsoft
Shared\VBA\VBA6\VBE6EXT.OLB"
#import "C:\\Program Files\\Microsoft Office\\Office\\excel9.olb"
rename("DialogBox","DialogBoxXl") rename("RGB","RGBXl") exclude
("IFont","IPicture")

using namespace Excel;

CoInitialize(NULL);
_ApplicationPtr pXl;

hr = pXl.CreateInstance(L"Excel.Application");
WorkbooksPtr pBooks = pXl-Workbooks;

// Open spreadsheet.
pBooks-Open("C:\\Temp\\MySpreadsheet.xls");
WorksheetsPtr pSheets = pXl-GetSheets();

// Get first sheet.
VARIANT vt;
::VariantInit(&vt);
vt.vt = VT_I2;
vt.iVal = (short)1;
_WorksheetPtr thisSheet = pSheets-GetItem(vt);

WCHAR tl[3] = { L'B', L'1', L'\0' };
WCHAR br[3] = { L'B', L'9', L'\0' };
VARIANT cellTL(::SysAllocString(tl));
VARIANT cellBR(::SysAllocString(br));
RangePtr range = a_sheet-GetRange(cellTL, cellBR);

// The VARIANT is an array of VARIANTs
VARIANT tcvt = range-GetValue();
if (tcvt.vt == (VT_ARRAY | VT_VARIANT))
{
// I know what the min and max col values are but was just
// getting used to the APIs.
SAFEARRAY * sa = tcvt.parray;
long colMax;
hr = ::SafeArrayGetUBound(sa, 1, &colMax);
long colMin;
hr = ::SafeArrayGetLBound(sa, 1, &colMin);

long index[2];
index[0] = 1;
for (long colIdx = colMin; colIdx <= colMax; colIdx++)
{
index[1] = colIdx;
VARIANT thisCell;
::VariantInit(&thisCell);
hr = SafeArrayGetElement(sa, index, &thisCell);
if (FAILED(hr))
{
...
}
}
}

The call to SafeArrayGetElement fails with error code E_INVALIDARG. The
calls to SafeArrayGetUBound are both successful and return what I
expect.
If anyone can offer any insight into why the SafeArrayGetElement fails
it would be greatly appreciated.

Many thanks,
Martin.