Question

I have a VSTO solution that corrects data in highlighted cells. The issue I am having is if the user selects an entire row/column, the program cycles through thousands of empty cells, long after the last populated cell has been processed.

My code looks like this:

        var addIn = Globals.ThisAddIn;
        Excel.Worksheet sheet = addIn.Application.ActiveSheet;
        Excel.Range range = addIn.Application.Selection;

        foreach (Excel.Range cell in range.Cells)
        {
            var val = cell.Value2;
            if (val == null)
                continue;

I've seen threads on how to use:

AdvancedFilter(Excel.XlFilterAction.xlFilterInPlace, Type.Missing)

But I can't seem to tie the two. I either want my "range" object to be limited to only populated cells or to be able to short-circuit my foreach loop when I have supassed the last value.

I thought of doing something like this:

if (cell.Row > populatedRange.Row ||
    cell.Column > populatedRange.Column)
    break;

But this has the potential of breaking the code if something other than an entire row/column is selected (user selects a cell outside of the populated range, and all subsequent populated cells are ignored).

I know I'm missing something simple, but my attempts (and searches) have not yielded the answer.

Was it helpful?

Solution

You can use the Range.SpecialCells method on the sheet to find the last cell. Then you can modify your loop to exit when you move beyond the last row or column. The following snippet will give your the row and column number of the last cell. You may still process some empty cells, but you won't be going all the way down to row 1048574.

Excel.Range last = Globals.Sheet1.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
int lastRowNumber = last.Row;
int lastColumnNumber = last.Column;

OTHER TIPS

Why don't you convert your range range.Cells into an array and deal with this in memory. Its way faster than iterating through each cell and then you can use all memory power of Linq or whatever to filter and correct your data... then you just send back to excel the updated range.

Doing:

var obj = range.Cell

will cast your range into object[,] of 2 dimensions. I think

System.Array myArray = (System.Array)(range.Cells)

would work too.

Regards.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top