# Named ranges

Named ranges let you give a friendly name to a cell range, scalar value, formula, or LAMBDA — and reference it from any formula. Spreadsheet supports four shapes that all interop with Excel:

| Shape             | Example                    | Use it as                                                  |
| ----------------- | -------------------------- | ---------------------------------------------------------- |
| **Range-typed**   | `MyRange = A1:B10`         | `=SUM(MyRange)`                                            |
| **Static value**  | `MyVal = 42`               | `=MyVal*2` — scalar returned directly                      |
| **Formula-typed** | `MyVar = =SUM(A1:A10)`     | `=MyVar` — virtual cell, recomputes when precedents change |
| **Named LAMBDA**  | `MyFunc = =LAMBDA(x, x*2)` | `=MyFunc(5)` returns 10                                    |

## Basic usage

Pass `namedRanges` to `useSpreadsheetState` + `CanvasGrid`. The hook returns CRUD callbacks the UI can wire to:

```tsx
import {
  SpreadsheetProvider,
  CanvasGrid,
  NamedRange,
} from "@rowsncolumns/spreadsheet";
import { useState } from "react";
import {
  useSpreadsheetState,
  NamedRangeEditor,
} from "@rowsncolumns/spreadsheet-state";

const MySpreadsheet = () => {
  const [namedRanges, onChangeNamedRanges] = useState<NamedRange[]>([]);
  const {
    onCreateNamedRange,
    onUpdateNamedRange,
    onDeleteNamedRange,
    onRequestDefineNamedRange,
    onRequestUpdateNamedRange,
  } = useSpreadsheetState({
    namedRanges,
    onChangeNamedRanges,
  });

  return (
    <>
      <CanvasGrid namedRanges={namedRanges} />
      <NamedRangeEditor
        namedRanges={namedRanges}
        onCreateNamedRange={onCreateNamedRange}
        onUpdateNamedRange={onUpdateNamedRange}
        onDeleteNamedRange={onDeleteNamedRange}
      />
    </>
  );
};

const App = () => (
  <SpreadsheetProvider>
    <MySpreadsheet />
  </SpreadsheetProvider>
);
```

The `NamedRangeEditor` component handles all four shapes — the user picks "Text or Formula" in the editor, and the engine resolves the type at evaluation time.

## Scoping — workbook vs sheet

Each name is either workbook-scoped (visible everywhere) or sheet-scoped (visible only on that sheet). When a sheet-scoped name shadows a workbook-scoped one with the same display name, Excel's lookup rules apply: **sheet-scope wins first**, then falls back to workbook scope.

```ts
const namedRanges: NamedRange[] = [
  // Workbook-scoped — visible everywhere
  { namedRangeId: "1", name: "Tax", value: "=0.08" },
  // Sheet-scoped — only on sheetId 1; overrides Tax on that sheet
  { namedRangeId: "2", name: "Tax", value: "=0.20", sheetId: 1 },
];

// On sheet 1: `=Tax` → 0.20
// On any other sheet: `=Tax` → 0.08
```

## Formula-typed names — the virtual-cell model

When `value` is a formula (`=SUM(A1:A10)`, `=price * 1.08`, etc.), the name becomes a first-class node in the calculation DAG. Cell formulas that reference the name get a real DAG input edge to that node, so the unified topological sort recomputes them whenever the named range's value changes.

```ts
const namedRanges: NamedRange[] = [
  { namedRangeId: "1", name: "price", value: "=A1" },
  { namedRangeId: "2", name: "fullPrice", value: "=price * 1.08" },
];

// Cell B1: =fullPrice
// When A1 changes → price recomputes → fullPrice recomputes → B1 recomputes
```

Order of registration doesn't matter — the engine does a two-pass batch register so `fullPrice` can reference `price` even if it's listed first.

## Named LAMBDAs — callable names

Set `value` to a LAMBDA expression and the engine treats the name as a callable function:

```ts
const namedRanges: NamedRange[] = [
  {
    namedRangeId: "1",
    name: "Commission",
    value: "=LAMBDA(sales, IF(sales > 1000, sales*0.1, sales*0.05))",
  },
];

// =Commission(500)  → 25
// =Commission(5000) → 500
```

Three resolution shapes are accepted on `onVariable`: a pre-built lambda value, a `{ref, value}` wrapper, or the raw `"=LAMBDA(...)"` source string (parsed + applied at call time). The fast-formula-parser engine handles all three identically.

## JSON round-trip

The DAG including all name → dependent edges is serializable. `Dag.toJSON` and `Dag.fromJSON` round-trip both directions of the cell ↔ named-range edges, so a rehydrated calculator matches the in-memory model exactly.


---

# 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/features/named-ranges.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.
