CellValue is a struct holding one cell’s value. Numbers, booleans and dates are kept
without being wrapped in an object, so walking a large number of cells allocates nothing.
The namespace is unvell.ReoGrid.Core.Data.
Kinds
One value is 16 bytes. An empty cell simply has the kind Empty and costs nothing extra.
Kind (CellValueKind) | What it holds |
|---|---|
Empty | nothing (default) |
Number | a double |
Boolean | 0 / 1 in the double |
DateTime | an OLE Automation date serial |
Text | an id into the shared string pool |
Error | an error code |
Reading
using unvell.ReoGrid.Core;
using unvell.ReoGrid.Core.Data;
CellValue v = ws.GetValue(0, 0);
switch (v.Kind)
{
case CellValueKind.Empty:
break;
case CellValueKind.Number:
Console.WriteLine(v.AsNumber);
break;
case CellValueKind.Boolean:
Console.WriteLine(v.AsBoolean);
break;
case CellValueKind.DateTime:
Console.WriteLine(DateTime.FromOADate(v.AsDateSerial));
break;
case CellValueKind.Text:
case CellValueKind.Error:
// strings and errors are held by id, so resolve them through the Worksheet
Console.WriteLine(ws.GetObjectValue(0, 0));
break;
}
The accessors do not check the kind. Look at Kind first, then use the matching accessor.
| Accessor | Valid for |
|---|---|
AsNumber | Number |
AsBoolean | Boolean |
AsDateSerial | DateTime (convert with DateTime.FromOADate) |
AsStringId | Text (a pool id, not the string itself) |
AsErrorCode | Error |
Writing
ws.SetValue(0, 0, CellValue.Number(1200));
ws.SetValue(0, 1, CellValue.Boolean(true));
ws.SetValue(0, 2, CellValue.Date(DateTime.Today.ToOADate()));
// strings always go through the Worksheet (they have to enter the shared pool)
ws.SetText(0, 3, "Notebook");
CellValue.Text(int) and CellValue.ErrorCode(int) take ids. An id only means anything once
it has been registered in the sheet’s pool, so there is no reason to call them from
application code. Use ws.SetText(...) for strings.
Empty cells
CellValue none = CellValue.Empty; // = default
bool isEmpty = ws.GetValue(5, 5).IsEmpty;
CellValue.Empty is the same as default. Reading a cell that holds nothing does not throw;
you get Empty back.
Which access route to use
| Situation | Use |
|---|---|
| You want a string to display or export | ws.GetDisplayText(r, c) |
| You want an ordinary .NET value | ws.GetObjectValue(r, c) |
| You are walking many cells and want to avoid allocation | ws.GetValue(r, c) / ws.ReadWindow(...) |
GetObjectValue resolves Text to a string and DateTime to a DateTime, which makes it
the easier choice most of the time. Reaching for CellValue directly pays off when you are
walking tens of thousands to millions of cells.
Equality
CellValue implements IEquatable<CellValue>, comparing kind and held value. For Text that
is an id comparison, so it is only meaningful between values from the same sheet’s pool.