V4 V5

Two types describe a position. Both are structs and both are zero-basedA1 is (0, 0).

The namespace is unvell.ReoGrid.Core.

CellPosition

using unvell.ReoGrid.Core;

var p = new CellPosition(2, 1);           // zero-based = B3
string a = p.ToAddress();                 // "B3"

var parsed = CellPosition.Parse("B3");    // "$B$3"; lowercase works too
if (CellPosition.TryParse("ZZ99", out var q))
	Console.WriteLine(q.ToAddress());

Parse accepts $-prefixed absolute notation and lowercase letters. An address beyond Excel’s dimensions is invalid: Parse throws and TryParse returns false.

Row and Col are read-only fields.

RangePosition

var r = new RangePosition(row: 3, col: 1, rows: 3, cols: 4);   // B4:E6
var bounds = RangePosition.FromBounds(3, 1, 5, 4);             // the same range, given by its corners

var parsed = RangePosition.Parse("B4:E6");
var single = RangePosition.Parse("A1");     // a single cell is a range too
var cols = RangePosition.Parse("A:C");      // whole column
var rows = RangePosition.Parse("3:5");      // whole row

string text = r.ToAddress();                // "B4:E6" - round-trips through Parse

The constructor takes a start position and a size (rows / cols). To build one from its corners, use FromBounds; corners given in either order are normalized.

ToAddress() returns a form that round-trips through Parse"A1" for a single cell, "A:C" for whole columns, "3:5" for whole rows, "A1:C3" otherwise.

Testing a range

int lastRow = r.EndRow;
int lastCol = r.EndCol;
int cells = r.CellCount;
bool one = r.IsSingleCell;
CellPosition anchor = r.TopLeft;

bool inside = r.Contains(4, 2);
bool covers = r.Contains(other);
bool overlaps = r.Intersects(other);
RangePosition merged = r.Union(other);

Union returns the smallest rectangle containing both ranges (not a set union).

Resolving in a sheet’s context

RangePosition carries no sheet information. A sheet-qualified reference like Sheet1!A1:B2 is not something RangePosition.Parse can handle, so use the sheet’s API.

// whole columns and rows clamp to the sheet's dimensions, and names resolve here
RangePosition cols = ws.ResolveRange("A:C");
RangePosition named = ws.ResolveRange("MyRange");

if (ws.TryResolveRange("a name that does not exist", out var found))
	Console.WriteLine(found.ToAddress());

ResolveRange differs from RangePosition.Parse in two ways.

  1. It clamps whole columns and rows to that sheet’s dimensions — resolving "A:C" on a 5,000-row sheet gives you 5,000 rows
  2. It resolves defined names — sheet scope wins over workbook scope

Given something it cannot resolve, ResolveRange throws and TryResolveRange returns false.

How Excel notation maps

NotationExampleHandling
Single cellA1Parses as a range with Rows = Cols = 1
Ordinary rangeB4:E6As written
Absolute$A$1:$C$3The $ is ignored; same range
Whole columnsA:CSpans 1,048,576 rows (clamp with ResolveRange)
Whole rows3:5Spans 16,384 columns (likewise)
Sheet-qualifiedSheet1!A1Not parseable — use ResolveRange or the defined-name API
Was this article helpful?