> For the complete documentation index, see [llms.txt](https://docs.rowsncolumns.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rowsncolumns.app/configuration/api/cell-data.md).

# Cell Data

`CellData` is the per-cell record stored in the array/record that builds sheet data. It bundles everything we need to round-trip a cell: the user-entered value, the calculated value, formatting, hyperlinks, validation, comments, protection flags, pivot/expand state, plus a handful of fields the calc engine uses internally.

Most fields exist in both a **long form** (`userEnteredValue`, `effectiveValue`, `userEnteredFormat`, `formattedValue`) and a **short form** (`ue`, `ev`, `uf`, `fv`). The short form is preferred for new writes — it keeps serialized payloads compact and is what the toolkit emits on save. The long forms still load for backwards compatibility.

The same naming convention applies one level down inside `ExtendedValue` — use `nv` / `sv` / `bv` / `fv` / `ev` instead of `numberValue` / `stringValue` / `boolValue` / `formulaValue` / `errorValue`.

```typescript
export type CellData<
  T extends StructuredResult = StructuredResult,
  M extends Mention = Mention,
> = {
  /**
   * The value the user entered in the cell. e.g, 1234, "Hello", or
   * "=NOW()". Dates, times, and datetimes are represented as doubles
   * in serial format.
   */
  ue?: ExtendedValue;
  /**
   * The effective value of the cell. For formula cells this is the
   * calculated result; for literal cells it equals `ue`. Read-only —
   * the calculation engine writes this. Set only when hydrating from
   * a saved snapshot.
   */
  ev?: ExtendedValue & StructuredValue<T>;
  /**
   * The formatted display string (after the number format is
   * applied). Read-only.
   */
  fv?: string;
  /**
   * The user-entered format. New writes are merged onto any existing
   * format. Can be a full `CellFormat` or a `StyleReference` (a short
   * `{ sid }` ref into the workbook's cellXfs registry) — the registry
   * dedupes repeated formats.
   */
  uf?: CellFormat | StyleReference;
  /**
   * Shared-strings key for cells whose value is interned in the
   * workbook's shared-strings table. Always a string. Per-segment
   * rich-text formatting (bold / italic / color / `@mention` chips)
   * rides on the SharedStrings entry as `{ text, runs }`; see the
   * [Rich text formatting](../features/rich-text-formatting.md)
   * feature page.
   */
  ss?: string;
  /**
   * Hyperlink target. Either a plain URL string or a structured value
   * carrying the URL + display label + tooltip.
   */
  hyperlink?: string | HyperlinkValue;
  /**
   * Data-validation rule attached to the cell. Inline rule object or
   * an ID reference into the sheet-level validation registry.
   */
  dataValidation?: DataValidationRule | DataValidationRuleRecord["id"];
  /**
   * Plain-text note (Excel "comment" — single-author, not threaded).
   */
  note?: string;
  /**
   * Pointer into the threaded-comment store (Excel 2016+ replies and
   * resolved state).
   */
  commentThreadId?: string | number;
  /**
   * Citation reference (FILTER source attribution, etc.).
   */
  citationId?: Citation["id"];
  /**
   * Cell-level protection flags. Only take effect when sheet protection
   * is enabled. `locked` defaults to true in Excel, so this field is
   * usually set to `{ locked: false }` to opt a cell OUT of protection.
   */
  protection?: {
    locked?: boolean;
    hidden?: boolean;
  };
  /**
   * Image URL — for cells whose value is an embedded image.
   */
  imageUrl?: string;
  /**
   * Cell metadata marker — currently only "people" for mention chips.
   */
  metaType?: "people";
  /**
   * Array-formula spill range in A1 notation ("B5:B20"). Only set on
   * the anchor cell of an array formula; spilled cells in the range
   * carry no `af`. Round-trips to / from <f t="array" ref="..."/> in
   * xlsx.
   */
  af?: string;
  /**
   * Conditional-formatting results keyed by rule ID. Written by the
   * CF evaluator; consumers shouldn't set this directly.
   */
  conditionalFormattingResultById?: Record<string, CustomFormulaResult>;
  /**
   * Result of a formula-based data-validation rule.
   */
  dataValidationResult?: CustomFormulaResult;
  /**
   * Outline / pivot grouping markers used by the canvas to render
   * expand-collapse chevrons.
   */
  expandable?: boolean;
  expanded?: boolean;
  /**
   * Pivot grouping key tuple for the cell.
   */
  groupKeys?: string[];
  childrenCount?: number;
  /**
   * Pivot table this cell belongs to.
   */
  pivotId?: PivotTable["pivotId"];
  /**
   * Collaboration / sync metadata.
   */
  version?: number;
  updatedAt?: number;

  // -------------------------------------------------------------------
  // Long-form aliases — kept for backwards compatibility with older
  // saved payloads. Prefer the short forms (`ue` / `ev` / `uf` / `fv`)
  // for new writes.
  // -------------------------------------------------------------------
  /** @deprecated use `ue` */
  userEnteredValue?: ExtendedValue;
  /** @deprecated use `ev` */
  effectiveValue?: ExtendedValue & StructuredValue<T>;
  /** @deprecated use `fv` */
  formattedValue?: string;
  /** @deprecated use `uf` */
  userEnteredFormat?: CellFormat | StyleReference;
};
```

{% hint style="info" %}
CellData is the source of truth of a cell. Spreadsheet does not mutate cellData — cells are rendered based on the properties on the record.
{% endhint %}

## ev and ue

`ev` (effective value) is derived from the value the user entered. If the user enters `"1000"`, Spreadsheet detects the type and classifies it as `nv` (number).

If the user enters `=SUM(4,4)`, `ev` is set when the calculation engine returns the result — `nv: 8` in this case.

Internally `ev` is used for calculations and `ue` is used for cell editing.

## uf and the effective format

All user-modified format changes are stored on `uf` (user-entered format). The effective format used at render time is **not** persisted on `CellData` — the renderer derives it on the fly from `uf`, the cell's effective value, and (for formula cells) precedent formats via `useSheetProperties.getEffectiveFormat`.

The legacy `effectiveFormat` / `ef` fields are accepted when loading older saved data but **should not be written**. New writes set `uf` only.

## Using your own CellData object

CanvasGrid accepts a custom CellData type that extends the core type:

```typescript
import {
  SpreadsheetProvider,
  CanvasGrid,
  CellData,
} from "@rowsncolumns/spreadsheet";

export type MyCustomCellData = CellData & {
  highlight?: boolean;
};

const App = () => {
  return (
    <SpreadsheetProvider>
      <CanvasGrid<MyCustomCellData>
        rowCount={1000}
        columnCount={1000}
        sheetId={1}
      />
    </SpreadsheetProvider>
  );
};
```
