---
url: /technical/reserved-variables.md
description: >-
  Reserved variables are variable names that are always available via
  VARIABLE(...), without needing to define them yourself.
---

# Reserved Variables

Reserved variables are variable names that are always available via `VARIABLE(...)`, without needing to define them with a [Variable component](/card-guides/variable) yourself. Where each one is available depends on where it's evaluated - a couple work in both Workviews and Cards, most are Card-specific, and several only make sense within a particular Card component.

Every row/column/list/node position below is **0-based** - the first row or column is `0`, not `1`.

::: warning Not available in Cube Formulas
None of the reserved variables below resolve inside a Cube's own cell formula. A cube formula calculates a value for the cube as a whole, not for a specific viewer or component, so there's no current user, row, or list position for it to read. If a calculation needs to vary by user, row, or list position, that logic belongs in a Set Instruction, a Card, or a Validation on the reporting layer instead - not in the cube formula itself. See [User-Based Validation](/technical/cube-validation-user-based) for a worked example.
:::

## Global

Available in both Workviews and Cards.

| Variable | Returns |
| --- | --- |
| `user-id` | The ID of the user currently running the Card or Workview. |
| `user-name` | The name of the user currently running the Card or Workview. |

## Card-wide

| Variable | Returns |
| --- | --- |
| `format` | The format the card is currently being rendered in: `live`, `png`, `pdf`, or `csv`. |
| `width` | The card's current rendered width, in pixels. |
| `height` | The card's current rendered height, in pixels. |
| `context-${dimension}` | The card's overall context for the named dimension, regardless of any narrower context a component within the card has set. For example, if a Table component overrides context to a single month, `VARIABLE("context-time")` still returns the card's broader Time context, not the table's narrowed one. |

::: warning Not all components get the full Card-wide set
[SQL Table](#sql-table) has its own, much smaller set of reserved variables and does **not** expose `context-${dimension}` or the rest of the Card-wide set above. SQL Table pulls from an external datasource rather than a Cube, so cube/dimension context doesn't carry across the same way it does for other components.
:::

## List

| Variable | Returns |
| --- | --- |
| `list-row` | The current row's index within the list. |
| `list-size` | The number of items in the list. |
| `list-first` | The element name for the first item in the list. If multiple elements are specified, they're concatenated with an underscore, e.g. `north-america_2024`. |
| `list-last` | The element name for the last item in the list, following the same concatenation rule as `list-first`. |
| `breadcrumbs` | The element context of the *current* row - same underscore-joined, lowercased, no-spaces format as `list-first`/`list-last`, but for whichever row is currently being evaluated rather than always the first or last. |

`breadcrumbs` compared against `list-first` or `list-last` is a common way to detect boundaries - for example, applying a style only to the first row of a list.

**Referencing a named List from elsewhere on the card.** The variables above only resolve from *inside* the List - a Text component sitting outside the List can't read them. Naming the List component exposes two of these more broadly:

| Variable | Returns |
| --- | --- |
| `{id}_page` | The List's current page. |
| `{id}_list-size` | The number of items in the List. |

`{id}` is the List's component ID, shown in the card editor's component tree - not a name you type yourself.

See the [List component](/card-guides/list) reference and the [Adding a list](/card-guides/adding-a-list) guide.

## Table & Grid

::: tip SQL Table is different
This section covers the Table and Grid components. [SQL Table](#sql-table) has its own, much smaller set of reserved variables.
:::

| Variable | Returns |
| --- | --- |
| `table-row` | The current row number. |
| `table-column` | The current column number. |
| `row-offset` | The row offset currently applied to the table (e.g. when the table is scrolled or paginated). |
| `row-list-size` | The number of items in the row list. |
| `row-list-first` | The element name for the first item in the row list. |
| `row-list-last` | The element name for the last item in the row list. |
| `column-list-size` | The number of items in the column list. |
| `column-list-first` | The element name for the first item in the column list. |
| `column-list-last` | The element name for the last item in the column list. |

**Referencing a named Table from elsewhere on the card.** The variables above only resolve from *inside* the table. Naming the Table component exposes a pagination-oriented set to the rest of the card, prefixed with the Table's Name property:

| Variable | Returns |
| --- | --- |
| `{table_name}-row-from` | The first row number shown on the current page. |
| `{table_name}-row-to` | The last row number shown on the current page. |
| `{table_name}-row-count` | The number of rows shown on the current page. |
| `{table_name}-total-rows` | The total number of rows across all pages. |
| `{table_name}-total-pages` | The total number of pages. |

These are the building blocks for pagination controls placed outside the table itself - a "Next page" button, or a "Showing X-Y of Z" label in a header. Since a control referencing `{table_name}-total-pages` needs the table to have already resolved its data, put it in a container with **Execute After** set to run once the table has rendered, rather than evaluating in parallel with it.

See the [Table component](/card-guides/table) reference, the [Adding a table](/card-guides/adding-a-table) guide, and [Filtering and Sorting Tables](/card-guides/table-filtering-and-sorting).

## SQL Table

[SQL Table](/card-guides/sql-table) pulls data directly from a datasource rather than a Cube, so it doesn't get the Global or Card-wide variables above, and its row/column variables use different names to [Table & Grid](#table-grid). The variables intended for use in formulas are:

| Variable | Returns |
| --- | --- |
| `colcount` | The number of columns in the table. |
| `table-row` | The current row number. |
| `row-list-size` | The number of items in the row list. |

There's no `table-column`, `column-list-size`, or `row-offset` equivalent for SQL Table - `colcount` is the closest thing to a column count, and there's no separate column-position variable.

You may also see `sql_query_id` appear (e.g. `7d319135-511f-4306-8e6e-5d1f53a2caed`) - this is reserved for MODLR's internal use in resolving the correct dataset for `SQLVALUE`, `SQLROW` and the table's other formula functions. It isn't meant to be referenced directly and doesn't correspond to anything in your datasource's own logs.

SQL Table also has its own set of formula functions for reading query results directly (`SQLCOLUMNNAME`, `SQLROW`, `SQLCOLUMN`, `SQLVALUE`) - see the [SQL Table component](/card-guides/sql-table) reference.

## Chart

| Variable | Returns |
| --- | --- |
| `plot-index` | The current plot's index number. |
| `plots-size` | The number of chart plots. |
| `plots-first` | The first chart plot element. |
| `plots-last` | The last chart plot element. |
| `series-index` | The current series' index number. |
| `series-size` | The number of chart series. |
| `series-first` | The first chart series element. |
| `series-last` | The last chart series element. |

**Example: cycling a colour palette per plot or series.** A chart doesn't know in advance how many plots or series it will end up with, so a colour can't just be hardcoded per line or bar. The common pattern is a plain comma-separated list of colours, with `SPLIT` combined with `NUMBER(VARIABLE("plot-index"))` (or `series-index`) picking the entry matching the current plot or series:

```
SPLIT(
    "#6B7280,#2563EB,#CCCCCC"
,
    ","
,
    NUMBER(VARIABLE("plot-index"))
)
```

[`SPLIT`](/cube-functions/split) picks out the entry at `plot-index`: plot `0` gets `#6B7280`, plot `1` gets `#2563EB`, plot `2` gets `#CCCCCC`, and so on. Add more colours to the list to extend the palette.

Put this formula on the chart's **Plot Color Formula** property to colour by plot, or **Series Color Formula** to colour by series (using `series-index` in place of `plot-index`) - every plot or series then picks its own colour automatically as they're added or removed from the Plot/Series Instructions, no manual per-plot or per-series colour assignment to maintain.

The colour list doesn't have to be hardcoded - it can just as easily be built from `LINK()` references elsewhere in the model, or any other string-producing formula, as long as the result is a comma-separated list of colours.

See the [Chart component](/card-guides/chart) reference for Plot Instructions and Series Instructions.

## Tree Graph

| Variable | Returns |
| --- | --- |
| `node-current-dimension` | The dimension the current node belongs to. |
| `node-current-name` | The current node's element name. |
| `node-current-full-name` | The current node's full name. |
| `node-parent-dimension` | The dimension the current node's parent belongs to. |
| `node-parent-name` | The current node's parent element name. |
| `node-parent-full-name` | The current node's parent's full name. |

::: tip name vs full-name
`node-current-name`/`node-parent-name` return the element name; the `full-name` variants return a fuller identifier (e.g. including alias or hierarchy path) - worth confirming the exact difference against your instance before relying on it, since it wasn't fully specified at time of writing.
:::

These resolve on any component placed inside a Tree Graph's node template, since each node applies its own context as it's rendered or drilled into. See [Tree Graph](/card-guides/tree-graph#using-components-in-the-tree) for how the node template works.

See [`VARIABLE`](/cube-functions/variable) for the general function reference.
