---
title: "Tables"
description: "You can turn a table into a chart and a chart into a table."
canonical_url: "https://tiptap-docs.lin52025i.qzz.io/diagrams/data/tables"
---

# Tables

You can turn a table into a chart and a chart into a table.

## Quick start

With [`chart.linkTables`](https://tiptap-docs.lin52025i.qzz.io/diagrams/data/tables.md#following-a-table) on, place the selection in a table and call:

```ts
editor.commands.insertLinkedChart({ type: 'bar' })
```

## Following a table

To let charts and diagrams follow tables, turn on the option
[`chart.linkTables`](https://tiptap-docs.lin52025i.qzz.io/diagrams/api-reference/options.md#linktables). It gives each table a `chartTableId` attribute,
so a chart can find its table again. Without it, `insertLinkedChart`, `linkChartToTable`, and
`setChartLayout` with a table return `false`.

A chart that follows a table changes in the same undo step as your edit of the table, so one undo
takes back both. The table can be anywhere in the document, and `listTables()` lists the tables
a chart can follow. The chart's data comes from the table through the `document-table`
[Data Source](https://tiptap-docs.lin52025i.qzz.io/diagrams/data/sources.md).

## How the table is read

`insertLinkedChart`, `linkChartToTable` and `updateLinkedTable` take `header` and `range`.

| Option          | Type                                 | Description                                                                                              |
| --------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------- |
| `header`        | `'auto' \| 'first-row' \| 'none'`    | Where the column names are. Default `'auto'`                                                             |
| `range.rows`    | `{ from?, to? }` or an array of them | The data rows read, counted from 0 below the header                                                      |
| `range.columns` | `(number \| { from?, to? })[]`       | The columns read, counted from 0, such as `[0, { from: 2 }]`. The first column read names the categories |

| `header`      | The column names                                                                           |
| ------------- | ------------------------------------------------------------------------------------------ |
| `'auto'`      | The first row, when it is made of header cells or holds no number outside the first column |
| `'first-row'` | The first row, whatever it holds                                                           |
| `'none'`      | Every row is data. The columns get default names                                           |

- Both ends of a range are included.
- A negative number counts from the end. `-1` is the last row, so `{ to: -2 }` leaves out a
  total row.
- Empty rows are not counted.
- Several ranges are read in the order given.
- A row or a column named twice is read once.
- Without `range`, a selection of cells in the table is the range: the rows and columns it covers,
  with the first column of the table as the label.
- `header` and `range` are stored in the chart's Data Source address. They apply to every later
  edit of the table.

## Commands

Turn a table into a chart and back, or a chart into an image that keeps its data:

> **Interactive demo:** [DiagramsConversions](https://embed-pro.tiptap.dev/preview/Extensions/DiagramsConversions)

### convertTableToChart

Replaces the table at the selection with a chart of its data.

```ts
editor.commands.convertTableToChart({ type: 'bar' })
```

| Option | Type        | Description                                            |
| ------ | ----------- | ------------------------------------------------------ |
| `type` | `ChartType` | The chart type. Defaults to `chart.defaultType`        |
| `pos`  | `number`    | A position inside the table. Defaults to the selection |

Returns `false` without a table.

### convertChartToTable

Replaces a chart with a plain table of its data.

```ts
editor.commands.convertChartToTable()
```

| Option | Type     | Description                                          |
| ------ | -------- | ---------------------------------------------------- |
| `pos`  | `number` | The chart's position. Defaults to the selected chart |

Returns `false` without a table in the schema.

### insertLinkedChart

Inserts a chart that follows a table.

```ts
editor.commands.insertLinkedChart({
  table: editor.storage.diagrams.listTables()[0].pos,
  type: 'bar',
  columns: { label: 'Month', series: ['Retail'] },
})

// A table without a header, without its last row
editor.commands.insertLinkedChart({
  table,
  header: 'none',
  range: { rows: { to: -2 } },
  columns: { label: 0, series: [2] },
})

// The first and the last two rows, and only the columns 0, 3 and 4
editor.commands.insertLinkedChart({
  table,
  range: { rows: [{ to: 0 }, { from: -2 }], columns: [0, { from: 3, to: 4 }] },
})
```

| Option    | Type                                                          | Description                                                                                                     |
| --------- | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `type`    | `ChartType`                                                   | The chart type. Defaults to `chart.defaultType`                                                                 |
| `table`   | `number`                                                      | The table's position, from `listTables()`. Defaults to the table at the selection                               |
| `columns` | `{ label?: string \| number, series?: (string \| number)[] }` | Columns by the text of their header cell or by their position from 0                                            |
| `header`  | `'auto' \| 'first-row' \| 'none'`                             | See [How the table is read](https://tiptap-docs.lin52025i.qzz.io/diagrams/data/tables.md#how-the-table-is-read) |
| `range`   | `{ rows?, columns? }`                                         | See [How the table is read](https://tiptap-docs.lin52025i.qzz.io/diagrams/data/tables.md#how-the-table-is-read) |
| `title`   | `string`                                                      | The chart's title                                                                                               |
| `below`   | `boolean`                                                     | `false` places the chart above the table. Default `true`                                                        |

`columns.label` names the categories and `columns.series` are drawn. Without `columns`, the
first column is the label and every other column is drawn. Positions also work for a table
without a header, and count among the columns that `range` reads.

The chart's data is read-only while it is linked.

Returns `false` without a table, without `chart.linkTables`, or when a name is not in the header
or a position is not in the table.

### updateLinkedTable

Changes how a chart or a diagram reads the table it follows, and reads the table again.

```ts
editor.commands.updateLinkedTable({ header: 'none' })
editor.commands.updateLinkedTable({ header: undefined, range: { rows: { from: 1 } } })
```

| Option   | Type                              | Description                                                                                                     |
| -------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `header` | `'auto' \| 'first-row' \| 'none'` | See [How the table is read](https://tiptap-docs.lin52025i.qzz.io/diagrams/data/tables.md#how-the-table-is-read) |
| `range`  | `{ rows?, columns? }`             | See [How the table is read](https://tiptap-docs.lin52025i.qzz.io/diagrams/data/tables.md#how-the-table-is-read) |
| `pos`    | `number`                          | The chart's or diagram's position. Defaults to the selected one                                                 |

- A key given as `undefined` goes back to the default.
- A key left out keeps its value.
- A chart's label and series stay on the same columns. They stay on the column itself while it
  is still read, otherwise on the column at the same position. So they survive a new header.
- `listCharts()` reports the current values as `tableRead`, and `listDiagrams()` as part of
  `link`.

Returns `false` for a chart or a diagram that follows no table or whose table is gone. For a
diagram, it also returns `false` when a column the diagram names is no longer there.

### setChartLayout

Decides whether a chart's table is in the document, and whether the chart shows.

```ts
editor.commands.setChartLayout({ layout: 'with-table' })
```

| Option   | Type                                 | Description                                          |
| -------- | ------------------------------------ | ---------------------------------------------------- |
| `layout` | `'chart' \| 'with-table' \| 'table'` | What you see in the document, see below              |
| `pos`    | `number`                             | The chart's position. Defaults to the selected chart |

| `layout`       | What you see                                                                                                     |
| -------------- | ---------------------------------------------------------------------------------------------------------------- |
| `'chart'`      | The chart. It holds its own data and follows no table                                                            |
| `'with-table'` | The chart and the table it follows. Each stands where you put it                                                 |
| `'table'`      | Only the table. The chart is still in the document, hidden directly below the table, and still follows the table |

What the command does depends on the chart's current layout:

| From           | To             | What happens                                                                                                                 |
| -------------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `'chart'`      | `'with-table'` | Inserts a table of the chart's data directly above the chart. The chart follows it, as with `insertLinkedChart`              |
| `'chart'`      | `'table'`      | Inserts that table, and hides the chart directly below it                                                                    |
| `'with-table'` | `'table'`      | Hides the chart. If the chart stands elsewhere, it moves directly below its table                                            |
| `'table'`      | `'with-table'` | Shows the chart again, where it stands                                                                                       |
| any            | `'chart'`      | Keeps the data the table last gave, and follows nothing. Removes the table, unless another chart or diagram still follows it |

- Where the chart and its table stand is not part of the layout. Move either node to move it.
- The title, the Renderer and the rest of the spec are kept, also while the chart is hidden. Any
  other layout shows the chart again as it was.
- The change is one undo step.
- A hidden chart is left out of `exportAll` and `exportDocx`. In HTML, its `<figure>` has the
  `hidden` attribute.
- Deleting or moving its table shows the chart again.
- To keep only a table and no chart, use `convertChartToTable`.
- `listCharts()` reports the current layout as `layout`.

Returns `true` when the chart has the layout afterwards, also when it had it already. Returns
`false` in these cases:

- For `'with-table'` and `'table'`, without table nodes in the schema or without the option
  `chart.linkTables`.
- For `'with-table'` and `'table'`, on a chart that follows no table and is linked to another
  read-only source, such as a read-only CSV URL.
- For `'table'`, when another hidden chart already stands directly below the table, or when the
  chart cannot stand there.

### linkChartToTable

Makes a chart follow a table that is already in the document, wherever that table stands.

```ts
const [table] = editor.storage.diagrams.listTables()
if (table) editor.commands.linkChartToTable({ table: table.pos })
```

| Option     | Type                              | Description                                                                                                  |
| ---------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `table`    | `number`                          | The table's position, as `listTables()` reports it                                                           |
| `pos`      | `number`                          | The chart's position. Defaults to the selected chart                                                         |
| `readOnly` | `boolean`                         | `false` keeps the chart's data editable while linked. Default `true`                                         |
| `header`   | `'auto' \| 'first-row' \| 'none'` | As for [`insertLinkedChart`](https://tiptap-docs.lin52025i.qzz.io/diagrams/data/tables.md#insertlinkedchart) |
| `range`    | `{ rows?, columns? }`             | As for [`insertLinkedChart`](https://tiptap-docs.lin52025i.qzz.io/diagrams/data/tables.md#insertlinkedchart) |

The table gets an id if it has none. The chart takes the table's data at once.

The chart ends with layout `'with-table'`, as with `setChartLayout({ layout: 'with-table' })`.
The difference is that `linkChartToTable` replaces the chart's data with an existing table's
data, while `setChartLayout` creates a new table from the chart's data, directly above the
chart.

Returns `false` without `chart.linkTables`, for a position that holds no table, and for a table
that is a Quick Input shown as a table.
