H
Henry
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.
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.