Sheet Class
The UserSheet interface provides the public API for manipulating spreadsheet data programmatically. It offers comprehensive methods for data access, manipulation, and history management.
Overview
Section titled “Overview”The UserSheet interface provides access to:
- Cell data retrieval and manipulation
- Row and column operations
- History and undo/redo functionality
- Sort and filter operations
- Cross-sheet communication
Important: When using sheet methods that return a new UserSheet instance (like update, write, setHeaderHeight, etc.), you must call apply() to apply the changes to the GridSheet component. The sheet instance alone is not sufficient to update the UI.
UserSheet vs Sheet
Section titled “UserSheet vs Sheet”UserSheet is the public interface exposed to application code — callbacks (onChange, onInit, etc.), sheetRef, and all documented methods operate on UserSheet. It intentionally exposes only stable, public APIs.
Sheet is the concrete class that implements UserSheet. It contains additional internal methods (such as getSystem()) that are marked @internal and are not part of the public API contract. These may change without notice.
In practice, Sheet implements UserSheet, so sheet.__raw__ simply returns this — the same object, typed as Sheet.
Accessing the Sheet class via __raw__
Section titled “Accessing the Sheet class via __raw__”If you need Sheet-level internals (e.g. getSystem()), use sheet.__raw__:
import { Sheet } from '@gridsheet/react-core';
const book = useBook({ onChange: ({ sheet }) => { const raw: Sheet = sheet.__raw__; const system = raw.getSystem({ y: 1, x: 1 }); console.log('changedTime:', system?.changedTime); },});Warning:
__raw__and any methods accessed through it are internal APIs. They are not covered by semver guarantees and may change or be removed in future versions. PreferUserSheetmethods wherever possible.
Core Properties
Section titled “Core Properties”| Property | Type | Description |
|---|---|---|
name | string | The sheet name |
changedTime | number | Timestamp (ms since epoch) of the most recent change |
lastChangedTime | number | undefined | Timestamp (ms since epoch) of the previous change |
area | AreaType | Current sheet boundaries { top, left, bottom, right } |
top, left, bottom, right | number | Current sheet boundaries (individual accessors) |
numRows | number | Number of data rows |
numCols | number | Number of data columns |
shape | { rows: number; cols: number } | Number of data rows and columns |
minNumRows, maxNumRows | number | Row count limits (-1 means unlimited) |
minNumCols, maxNumCols | number | Column count limits (-1 means unlimited) |
headerWidth, headerHeight | number | Header dimensions in pixels |
Data Access Methods
Section titled “Data Access Methods”Cell Retrieval
Section titled “Cell Retrieval”getCell(point: PointType, options?: { resolution?: Resolution; raise?: boolean }): CellType | undefined
Section titled “getCell(point: PointType, options?: { resolution?: Resolution; raise?: boolean }): CellType | undefined”Retrieves a cell by its coordinates.
resolution: controls how formula values are resolved — see the Resolution section belowraise: Iftrue, throws on formula errors instead of returning them
const cell = sheet.getCell({ y: 1, x: 1 });console.log(cell?.value, cell?.style);
// Get the raw formula string without evaluationconst raw = sheet.getCell({ y: 1, x: 1 }, { resolution: 'RAW' });getPolicy(point: PointType): PolicyType
Section titled “getPolicy(point: PointType): PolicyType”Returns the Policy instance applied to a cell.
const policy = sheet.getPolicy({ y: 1, x: 1 });getRectSize(area: AreaType): RectType
Section titled “getRectSize(area: AreaType): RectType”Returns the pixel dimensions and position of a cell area. RectType is { y: number; x: number; height: number; width: number }.
const rect = sheet.getRectSize({ top: 1, left: 1, bottom: 3, right: 3 });console.log(rect.width, rect.height, rect.x, rect.y);getSerializedValue(props: { point: PointType; cell?: CellType; resolution?: Resolution }): string
Section titled “getSerializedValue(props: { point: PointType; cell?: CellType; resolution?: Resolution }): string”Serializes a cell’s value to a string using its policy.
const str = sheet.getSerializedValue({ point: { y: 1, x: 1 } });getLastChangedAddresses(): Address[]
Section titled “getLastChangedAddresses(): Address[]”Returns addresses of cells changed in the last operation.
const changed = sheet.getLastChangedAddresses();console.log(changed); // e.g. ['A1', 'B2']Reading Sheet Data with toXXX Functions
Section titled “Reading Sheet Data with toXXX Functions”To export or read the sheet data in bulk, use the standalone toXXX utility functions exported from @gridsheet/react-core. These functions take a UserSheet as their first argument and are not methods on the sheet object itself.
import { toValueMatrix, toValueObject, toValueRows, toValueCols, toCellMatrix, toCellObject, toCellRows, toCellCols,} from '@gridsheet/react-core';All toXXX functions accept an optional second argument with these common options:
| Option | Type | Default | Description |
|---|---|---|---|
resolution | 'RESOLVED' | 'EVALUATED' | 'RAW' | 'SYSTEM' | 'RESOLVED' | How formula values are resolved — see Resolution |
raise | boolean | false | Throw on formula errors instead of returning them |
filter | CellFilter | (all cells) | Predicate to include/exclude cells |
asScalar | boolean | false | Convert values to scalar via the cell’s policy |
Resolution
Section titled “Resolution”The resolution option controls how formula results are resolved when reading cells.
| Value | Description |
|---|---|
'RESOLVED' | (default) Fully evaluates formulas to a scalar. Range references like =C1:F1 are unwrapped to the top-left scalar value. |
'EVALUATED' | Evaluates formulas one level deep but preserves range results as a Sheet object. Use this in renderSheet policy hooks to receive the full range. |
'RAW' | Returns the formula string with addresses resolved to display form; does not evaluate. |
'SYSTEM' | Returns the raw stored value with no evaluation or transformation. |
// Default: =C1:F1 → scalar value of C1sheet.getCell({ y: 1, x: 2 });
// EVALUATED: =C1:F1 → Sheet object spanning C1:F1sheet.getCell({ y: 1, x: 2 }, { resolution: 'EVALUATED' });
// RAW: =C1:F1 → '=C1:F1' stringsheet.getCell({ y: 1, x: 2 }, { resolution: 'RAW' });'EVALUATED' is particularly useful when writing a renderSheet policy mixin — Policy.render() internally uses 'EVALUATED' so that range formulas arrive as Sheet objects:
const ChartPolicyMixin: PolicyMixinType = { renderSheet({ value }: RenderProps<UserSheet>) { // value is the Sheet spanning the referenced range (e.g. C1:F1) const matrix = toValueMatrix(value); // ... render chart from matrix data },};Value Functions
Section titled “Value Functions”toValueMatrix(sheet, args?: ToValueMatrixProps): any[][]
Section titled “toValueMatrix(sheet, args?: ToValueMatrixProps): any[][]”Returns cell values as a 2D array (rows × columns).
const matrix = toValueMatrix(sheet);// [[1, 2, 3], [4, 5, 6], ...]
// Only a specific areaconst area = toValueMatrix(sheet, { area: { top: 1, left: 1, bottom: 3, right: 3 } });
// Unevaluated formula stringsconst raw = toValueMatrix(sheet, { resolution: 'RAW' });toValueObject(sheet, args?: ToValueObjectProps): { [address: Address]: any }
Section titled “toValueObject(sheet, args?: ToValueObjectProps): { [address: Address]: any }”Returns cell values as an object keyed by address (e.g. 'A1').
const values = toValueObject(sheet);console.log(values['A1']); // value of A1
// Only specific addressesconst partial = toValueObject(sheet, { addresses: ['A1', 'B2', 'C3'] });toValueRows(sheet, args?: ToValueRowsProps): { [col: string]: any }[]
Section titled “toValueRows(sheet, args?: ToValueRowsProps): { [col: string]: any }[]”Returns an array of objects, one per row, mapping column letter to value.
const rows = toValueRows(sheet);console.log(rows[0]); // { A: 1, B: 'hello', ... } for row 1
// Only specific rows (1-based)const subset = toValueRows(sheet, { rows: [1, 3, 5] });toValueCols(sheet, args?: ToValueColsProps): { [row: string]: any }[]
Section titled “toValueCols(sheet, args?: ToValueColsProps): { [row: string]: any }[]”Returns an array of objects, one per column, mapping row number to value.
const cols = toValueCols(sheet);console.log(cols[0]); // { '1': 1, '2': 4, ... } for column A
// Only specific columns (1-based index or letter)const subset = toValueCols(sheet, { cols: ['A', 'C'] });Cell Object Functions
Section titled “Cell Object Functions”The toCellXXX variants return full CellType objects instead of plain values, giving access to styles and other metadata.
toCellMatrix(sheet, args?: ToCellMatrixProps): (CellType | null)[][]
Section titled “toCellMatrix(sheet, args?: ToCellMatrixProps): (CellType | null)[][]”Returns full cell objects as a 2D array.
const matrix = toCellMatrix(sheet);console.log(matrix[0][0]?.value);console.log(matrix[0][0]?.style);toCellObject(sheet, args?: ToCellObjectProps): CellsByAddressType
Section titled “toCellObject(sheet, args?: ToCellObjectProps): CellsByAddressType”Returns full cell objects keyed by address.
const cells = toCellObject(sheet);console.log(cells['A1']?.style);toCellRows(sheet, args?: ToCellRowsProps): CellsByAddressType[]
Section titled “toCellRows(sheet, args?: ToCellRowsProps): CellsByAddressType[]”Returns an array of cell-objects-by-column-letter, one entry per row.
const rows = toCellRows(sheet);console.log(rows[0]); // { A: CellType, B: CellType, ... } for row 1toCellCols(sheet, args?: ToCellColsProps): CellsByAddressType[]
Section titled “toCellCols(sheet, args?: ToCellColsProps): CellsByAddressType[]”Returns an array of cell-objects-by-row-number, one entry per column.
const cols = toCellCols(sheet);console.log(cols[0]); // { '1': CellType, '2': CellType, ... } for column AExample: Reading data in an onChange handler
Section titled “Example: Reading data in an onChange handler”import { GridSheet, useBook, toValueMatrix } from '@gridsheet/react-core';
function MyComponent() { const book = useBook({ onChange: ({ sheet }) => { const matrix = toValueMatrix(sheet); console.log('Current values:', matrix); }, });
return ( <GridSheet book={book} initialCells={{ A1: { value: 1 }, B1: { value: 2 } }} /> );}Data Manipulation Methods
Section titled “Data Manipulation Methods”Important: All data manipulation methods return a new UserSheet instance. To apply changes to the GridSheet component, you must call apply with the returned sheet via sheetRef.
Using Sheet References
Section titled “Using Sheet References”To manipulate sheet data programmatically, use sheetRef (inside a component) or createSheetRef (outside a component):
React (useSheetRef)
Section titled “React (useSheetRef)”useSheetRef is a React hook and must be called within a function component:
import { useSheetRef, GridSheet } from '@gridsheet/react-core';
function MyComponent() { const sheetRef = useSheetRef();
const handleUpdate = () => { if (!sheetRef.current) return; const { sheet, apply } = sheetRef.current; const newSheet = sheet.write({ point: { x: 1, y: 1 }, value: 'New Value' }); apply(newSheet); };
return ( <GridSheet sheetRef={sheetRef} initialCells={initialCells} /> );}Global Usage (createSheetRef)
Section titled “Global Usage (createSheetRef)”For global usage or use outside a React component:
import { createSheetRef, GridSheet } from '@gridsheet/react-core';
const sheetRef = createSheetRef();
function MyComponent() { return ( <GridSheet sheetRef={sheetRef} initialCells={initialCells} /> );}
// Can be called from anywhere:function updateFromOutside() { if (!sheetRef.current) return; const { sheet, apply } = sheetRef.current; const newSheet = sheet.write({ point: { x: 1, y: 1 }, value: 'Hello' }); apply(newSheet);}Cell Updates
Section titled “Cell Updates”Note: The apply function and sheet object in the examples below are obtained from sheetRef.current.
update(args): UserSheet
Section titled “update(args): UserSheet”update(args: { diff: CellsByAddressType; historicize?: boolean; partial?: boolean; updateChangedTime?: boolean; reflection?: StorePatchType;}): UserSheetUpdates multiple cells at once.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;
const newSheet = sheet.update({ diff: { 'A1': { value: 'Updated Value' }, 'B1': { style: { color: '#FF0000' } }, }, historicize: true,});apply(newSheet); // Required to apply changeswrite(args): UserSheet
Section titled “write(args): UserSheet”write(args: { point: PointType; value: string; updateChangedTime?: boolean; reflection?: StorePatchType;}): UserSheetWrites a value to a specific cell.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;
const newSheet = sheet.write({ point: { x: 1, y: 1 }, value: 'Hello World',});apply(newSheet); // Required to apply changeswriteMatrix(args): UserSheet
Section titled “writeMatrix(args): UserSheet”writeMatrix(args: { point: PointType; matrix: MatrixType<string>; updateChangedTime?: boolean; reflection?: StorePatchType;}): UserSheetWrites a 2D matrix of string values starting at a specific point.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;
const newSheet = sheet.writeMatrix({ point: { x: 1, y: 1 }, matrix: [['A1', 'B1'], ['A2', 'B2']],});apply(newSheet); // Required to apply changesRow Operations
Section titled “Row Operations”insertRows(args): UserSheet
Section titled “insertRows(args): UserSheet”insertRows(args: { y: number; numRows: number; baseY: number; diff?: CellsByAddressType; partial?: boolean; updateChangedTime?: boolean; reflection?: StorePatchType;}): UserSheetInserts rows at position y. baseY specifies which existing row to copy layout from. If diff is provided, those cells are updated after insertion.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;
const newSheet = sheet.insertRows({ y: 5, numRows: 2, baseY: 5, diff: { A5: { value: 'New Row 1' }, A6: { value: 'New Row 2' }, },});apply(newSheet); // Required to apply changesremoveRows(args): UserSheet
Section titled “removeRows(args): UserSheet”removeRows(args: { y: number; numRows: number; reflection?: StorePatchType }): UserSheetRemoves rows starting at position y.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;
const newSheet = sheet.removeRows({ y: 2, numRows: 3 });apply(newSheet); // Required to apply changesColumn Operations
Section titled “Column Operations”insertCols(args): UserSheet
Section titled “insertCols(args): UserSheet”insertCols(args: { x: number; numCols: number; baseX: number; diff?: CellsByAddressType; partial?: boolean; updateChangedTime?: boolean; reflection?: StorePatchType;}): UserSheetInserts columns at position x. baseX specifies which existing column to copy layout from. If diff is provided, those cells are updated after insertion.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;
const newSheet = sheet.insertCols({ x: 3, numCols: 2, baseX: 3, diff: { C1: { value: 'New Col 1' }, D1: { value: 'New Col 2' }, },});apply(newSheet); // Required to apply changesremoveCols(args): UserSheet
Section titled “removeCols(args): UserSheet”removeCols(args: { x: number; numCols: number; reflection?: StorePatchType }): UserSheetRemoves columns starting at position x.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;
const newSheet = sheet.removeCols({ x: 2, numCols: 3 });apply(newSheet); // Required to apply changesMove and Copy Operations
Section titled “Move and Copy Operations”move(args): UserSheet
Section titled “move(args): UserSheet”Moves cells from one area to another.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;
const newSheet = sheet.move({ src: { top: 1, left: 1, bottom: 3, right: 3 }, dst: { top: 5, left: 5, bottom: 7, right: 7 },});apply(newSheet); // Required to apply changescopy(args): UserSheet
Section titled “copy(args): UserSheet”Copies cells from one area to another. Pass onlyValue: true to copy only values without styles.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;
const newSheet = sheet.copy({ src: { top: 1, left: 1, bottom: 3, right: 3 }, dst: { top: 5, left: 5, bottom: 7, right: 7 }, onlyValue: false,});apply(newSheet); // Required to apply changesHeader Operations
Section titled “Header Operations”setHeaderHeight(height: number, historicize?: boolean): UserSheet
Section titled “setHeaderHeight(height: number, historicize?: boolean): UserSheet”Sets the row header height in pixels.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;apply(sheet.setHeaderHeight(32));setHeaderWidth(width: number, historicize?: boolean): UserSheet
Section titled “setHeaderWidth(width: number, historicize?: boolean): UserSheet”Sets the column header width in pixels.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;apply(sheet.setHeaderWidth(60));Sort and Filter Operations
Section titled “Sort and Filter Operations”Rows marked with sortFixed: true or filterFixed: true (via their row header cell) are exempt from sort reordering and filter hiding respectively. See Fixed Rows in the Props reference.
sortRows(args: { x: number; direction: 'asc' | 'desc' }): UserSheet
Section titled “sortRows(args: { x: number; direction: 'asc' | 'desc' }): UserSheet”Sorts all data rows by the values in the specified column. Supports ascending and descending order. Null/undefined values are sorted to the end. Rows with sortFixed: true on their header cell remain in place. This operation is recorded in the undo/redo history.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;
// Sort by column B ascendingapply(sheet.sortRows({ x: 2, direction: 'asc' }));
// Sort by column A descendingapply(sheet.sortRows({ x: 1, direction: 'desc' }));filterRows(args?: { x?: number; filter?: FilterConfig }): UserSheet
Section titled “filterRows(args?: { x?: number; filter?: FilterConfig }): UserSheet”Applies a filter to the specified column. Rows that do not match the filter conditions are hidden. Rows with filterFixed: true on their header cell are always visible regardless of filter conditions. Multiple columns can have independent filters, and they are combined with AND logic across columns.
If called without filter, clears the filter for the specified column. If called without x, clears all column filters.
The FilterConfig object has the following structure:
type FilterConfig = { mode: 'and' | 'or'; // How multiple conditions are combined conditions: FilterCondition[];};
type FilterCondition = { method: FilterConditionMethod; // e.g., 'eq', 'contains', 'gt', etc. value: string[];};Available filter methods:
| Method | Description |
|---|---|
eq | Equals |
ne | Not equals |
gt | Greater than |
gte | Greater than or equal |
lt | Less than |
lte | Less than or equal |
includes | Contains substring |
excludes | Does not contain substring |
blank | Cell is empty (no value required) |
nonblank | Cell is not empty (no value required) |
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;
// Filter column B: show only rows where value > 80apply(sheet.filterRows({ x: 2, filter: { mode: 'or', conditions: [{ method: 'gt', value: ['80'] }], },}));
// Clear filter on column B onlyapply(sheet.filterRows({ x: 2 }));
// Clear all filtersapply(sheet.filterRows());isRowFiltered(y: number): boolean
Section titled “isRowFiltered(y: number): boolean”Returns true if the specified row is currently hidden by a filter.
if (sheet.isRowFiltered(3)) { console.log('Row 3 is hidden by a filter');}hasActiveFilters(): boolean
Section titled “hasActiveFilters(): boolean”Returns true if any column currently has an active filter.
if (sheet.hasActiveFilters()) { console.log('Some rows are filtered');}Async Resolution
Section titled “Async Resolution”GridSheet is virtualized: normally only the cells the UI renders are solved. That keeps large sheets fast, but it means an off-screen cell whose formula calls an async function never fires until you scroll it into view. These methods let you resolve async cells regardless of the visible range.
resolveAll(): number
Section titled “resolveAll(): number”Fires every off-screen async formula cell in this sheet, ignoring the visible range, and returns the number of async cells visited.
Only cells whose formula calls an async function are visited — sync formulas have no side effects and resolve on read, so they are skipped. Cells already resolved (cache hit) or in flight are not re-fired, so repeated calls converge and are cheap. To read the resolved values, await waitForPending() afterwards.
if (!sheetRef.current) return;const { sheet } = sheetRef.current;
sheet.resolveAll(); // fire all off-screen async cellsawait sheet.waitForPending(); // wait until they settle
// Now serialization returns resolved values for off-screen rows too.const matrix = toValueMatrix(sheet);This is the on-demand building block behind the eager sheet option. Use the option to resolve continuously as the sheet changes, or call resolveAll() yourself (e.g. right before saving) to pay the cost only when you need every row materialized.
waitForPending(): Promise<void>
Section titled “waitForPending(): Promise<void>”Resolves once all in-flight async formula computations have completed and no cell holds a pending value. Resolves immediately if nothing is pending. Useful before reading values, sorting, or filtering so that async results are fully settled.
hasPendingCells(): boolean
Section titled “hasPendingCells(): boolean”Returns true if any cell currently holds a pending (unresolved) async value.
History (Undo/Redo)
Section titled “History (Undo/Redo)”undo(): { history: HistoryType | null }
Section titled “undo(): { history: HistoryType | null }”Undoes the most recent operation.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;const { history } = sheet.undo();apply(sheet);redo(): { history: HistoryType | null }
Section titled “redo(): { history: HistoryType | null }”Redoes the most recently undone operation.
if (!sheetRef.current) return;const { sheet, apply } = sheetRef.current;sheet.redo();apply(sheet);histories(): HistoryType[]
Section titled “histories(): HistoryType[]”Returns all undo/redo history entries.
historyIndex(): number
Section titled “historyIndex(): number”Returns the current position in the history stack.
historySize(): number
Section titled “historySize(): number”Returns the total number of history entries.
Async Formulas
Section titled “Async Formulas”hasPendingCells(): boolean
Section titled “hasPendingCells(): boolean”Returns true if any cells with async formulas are still loading.
waitForPending(): Promise<void>
Section titled “waitForPending(): Promise<void>”Resolves when all pending async formula cells have settled.
if (!sheetRef.current) return;const { sheet } = sheetRef.current;await sheet.waitForPending();const matrix = toValueMatrix(sheet);