Как выполнить итерацию коллекции столбцов Excel в C++ с помощью автоматизации?

Я хочу сделать моральный эквивалент следующего кода VBA:

For Each col In Worksheets("Sheet1").Columns
    # do stuff
Next col

Я сгенерировал оболочки MFC для библиотеки типов Excel, которые дошли до меня (все сгенерированные типы являются производными от COleDispatchDriver :

CApplication app;
app.CreateDispatch( clsid, e );

CWorkbooks  wbks( app.get_Workbooks() );
CWorkbook   book( wbks.Open( filename, /* optional args */ ) );
CRange      cols( app.get_Columns() );
long        numCols = cols.get_Count();

и оттуда я застрял. Похоже, я могу как бы перебирать ячейки, используя Range::get_Item( rowid, colid ), а затем получать столбец из ячейки, но я искал более прямой перевод вышеупомянутого цикла.

(РЕДАКТИРОВАТЬ) Уточнение: на самом деле я не забочусь об отдельных ячейках. Моя цель - определить, какие столбцы имеют ширину 0 (скрыты) и удалить их с рабочего листа.

Ответов (2)

Решение

Я предполагаю, что вы пытаетесь пройти по всем ячейкам в электронной таблице. Вы можете получить диапазон "всех ячеек" активного рабочего листа и просмотреть его строки и столбцы в цикле:

CSheets sheets = book.get_WorkSheets();
CWorkSheet sheet = sheets.get_ActiveSheet();
Range cells = sheet.get_Cells();

int nRows = cells.get_Rows().get_Count();
int nCols = cells.get_Columns().get_Count();

for (int i = 0; i <= nRows; i++)
    {
    for (int j = 0; j <= nCols; j++)
        {
        Range cell = cells.get_Item(i+1,j+1);
        //Do stuff with individual cell
        }
     }

РЕДАКТИРОВАТЬ: В ответ на разъяснение OP:

Это, вероятно, сделает то, что вы ищете:

CSheets sheets = book.get_WorkSheets();
CWorkSheet sheet = sheets.get_ActiveSheet();
Range cols= sheet.get_Columns();
int nCols = cols.get_Count();

for (int i = nCols; i > 0; i--)
    {         
    Range topCellOfCol = cells.get_Item(1, i);
    Range entireCol = topCellOfCol.get_EntireColumn();
    if (entireCol.get_Hidden())
         entireCol.Delete( xlShiftToLeft );        
    }

Благодаря Стиву я добился большей части пути. Оказывается, несмотря на документацию Excel VBA, Range :: Item ведет себя по-разному в зависимости от того, как создается диапазон; таким образом:

COleVariant OPTIONAL( (long)DISP_E_PARAMNOTFOUND, VT_ERROR );

Range cols = sheet.get_Columns();
for ( long i = cols.get_Count(); i > 0; --i )
{
    Range col = cols.get_Item( COleVariant( i ), OPTIONAL ) ;
    // ...
}

будет перебирать диапазоны, представляющие столбцы, и

Range rows = sheet.get_Rows();
for ( long i = rows.get_Count(); i > 0; --i )
{
    Range row = cols.get_Item( COleVariant( i ),  OPTIONAL );
    // ...
}

будет перебирать диапазоны, представляющие строки. Это подразумевается в примерах VBA, но фактически не указано в документации.