# 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.
   */
  ss?: string;
  /**
   * Text-format runs for rich-text cells — colored / bold / italic
   * segments and `@user` mentions.
   */
  textFormatRuns?: TextFormatRun<TextFormat, M>[];
  /**
   * 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>
  );
};
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.rowsncolumns.app/configuration/api/cell-data.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
