HOW TO: How do I find the last populated cell in a range?
Reference: Q0050
Article last modified on 2-Jun-2008
The information in this article applies to:
- XLL+ for Visual Studio 2005 - 5.0
- XLL+ for Visual Studio .NET - 4.2, 4.3.1, 5.0
- XLL+ for Visual Studio 6 - 3, 4.1, 4.2, 4.3.1, 5.0
HOW TO: How do I find the last populated cell in a range?
Question
How can I do the equivalent of VBA's Range.End(xlDown)
?
Answer
Construct a refence to the cell you want to start at, and then use the CXlRef class and CXlOper::Coerce() to iterate the cell reference until you encounter an empty cell.
The code below will inspect the cells starting with the specified cell reference and moving in the specified direction:
enum { xlUp, xlLeft, xlDown, xlRight }; int CountPopulatedCells(const CXlOper& xloRef, int direction) { if (!xloRef.IsRef()) return -1; CXlOper xloCell = xloRef, xloValue; CXlRef xlr = xloRef.GetRef(); xlr.Right() = xlr.Left(); xlr.Bottom() = xlr.Top(); xloCell.GetRef() = xlr; int count = 0; while (true) { // Is cell empty? if (xloValue.Coerce(xloCell) != 0) return -1; if (xloValue.IsEmpty()) break; count++; // Move to next cell if (direction == xlUp) { if (xlr.Top() == 0) break; else xlr.Bottom() = --xlr.Top(); } else if (direction == xlLeft) { if (xlr.Left() == 0) break; else xlr.Right() = --xlr.Left(); } else if (direction == xlDown) { if (xlr.Top() == CXlRef::MaxRow()) break; else xlr.Bottom() = ++xlr.Top(); } else if (direction == xlRight) { if (xlr.Left() == CXlRef::MaxCol()) break; else xlr.Right() = ++xlr.Left(); } else return -1; xloCell.GetRef() = xlr; } return count; }
Example
//{{XLP_SRC(RangeEndDown) // NOTE - the FunctionWizard will add and remove mapping code here. // DO NOT EDIT what you see in these blocks of generated code! IMPLEMENT_XLLFN2(RangeEndDown, "R", "RangeEndDown", "", "User Defined", "Returns the number of populated cells in" " the range starting at the active cell and moving down", "", "appscope=1\0", 2) extern "C" __declspec( dllexport ) LPXLOPER RangeEndDown() { XLL_FIX_STATE; CXlOper xloResult; //}}XLP_SRC CXlOper xloRef; if (!xloRef.GetActiveCell()) CXllApp::XlMessageBox("Not a cell reference", XlMessageBoxTypeInformation); else { int count = CountPopulatedCells(xloRef, xlDown); char msg[128]; _snprintf(msg, sizeof(msg), "%d cells are populated", count); CXllApp::XlMessageBox(msg, XlMessageBoxTypeInformation); } return xloResult.Ret(); }
See also
CXlOper::IsEmpty() in the online documentation.
CXlOper::GetRef() in the online documentation.
CXlRef class
in the online documentation.