# Export And State
URL: https://pro.rv-grid.com/guides/pivot/concepts/export-state/
Source: src/content/docs/guides/pivot/concepts/export-state.mdx
Description: Export visible Pivot data to CSV, copy Pivot data as TSV, and save Pivot layout as JSON.
Pivot export helpers turn the current visible Pivot grid into plain text that users can download, paste, or save. Pivot state JSON saves the Pivot configuration so the same report layout can be restored later.

## What Each Format Is For

CSV means comma-separated values. Use CSV when users need a file they can open in Excel, Numbers, Google Sheets, or another reporting tool. The Pivot CSV helper flattens grouped column headers into readable header paths and appends pinned bottom rows, such as grand totals, after the body rows.

TSV means tab-separated values. Use TSV for copy and paste because spreadsheets understand tabs as cell boundaries. The Pivot TSV helper keeps row-axis headers and column-axis headers separated, which makes pasted Pivot output easier to read.

State JSON is not table data. It is a saved Pivot configuration, including fields such as rows, columns, values, filters, totals, collapsed state, and expanded groups. Use state JSON when users need to save a report layout, share a layout, or restore a layout after reloading the page.

## Basic Setup

Import the helpers from Enterprise with the Pivot plugin:

```ts
import {
  buildPivotCopyTsv,
  exportVisiblePivotToCsv,
  parsePivotStateJson,
  PivotPlugin,
  serializePivotStateJson,
  type PivotConfig,
} from '@revolist/revogrid-enterprise';
```

Render Pivot as usual:

```ts
const pivot: PivotConfig = {
  rows: ['region', 'channel'],
  columns: ['quarter'],
  values: [
    { prop: 'revenue', aggregator: 'sum', label: 'Revenue' },
    { prop: 'orders', aggregator: 'sum', label: 'Orders' },
  ],
  totals: {
    grandTotal: true,
    subtotals: true,
  },
};

grid.plugins = [PivotPlugin];
grid.pivot = pivot;
grid.source = rows;
```

## Read The Visible Grid Model

CSV and TSV helpers work from the current grid model, not from the original raw dataset. Pass the visible `columns`, visible `source`, and any `pinnedBottomSource`.

```ts
function readGridModel(grid: HTMLRevoGridElement & { pinnedBottomSource?: any[] }) {
  return {
    columns: grid.columns ?? [],
    source: grid.source ?? [],
    pinnedBottomSource: grid.pinnedBottomSource ?? [],
  };
}
```

This matters because Pivot generates columns and rows from the source data. Exporting the original array would miss generated value columns, grouped headers, subtotal rows, and grand-total rows.

## Export CSV

Use `exportVisiblePivotToCsv` when the user wants a file-oriented export:

```ts
const csv = exportVisiblePivotToCsv(readGridModel(grid));
```

For browser download:

```ts
const csv = exportVisiblePivotToCsv(readGridModel(grid));
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');

link.href = url;
link.download = 'pivot-report.csv';
link.click();

URL.revokeObjectURL(url);
```

CSV is best for file export, email attachments, imports into other systems, and audit snapshots.

## Copy TSV

Use `buildPivotCopyTsv` when the user wants clipboard text:

```ts
const tsv = buildPivotCopyTsv(readGridModel(grid));
await navigator.clipboard.writeText(tsv);
```

TSV is best for copy actions because pasting into a spreadsheet preserves cells without requiring the user to import a file.

You can also limit copy output when you know the selected props or selected rows:

```ts
const tsv = buildPivotCopyTsv({
  ...readGridModel(grid),
  selectedProps: ['region', '__pivot_grand_total__|revenue'],
  selectedRowIndexes: [0, 1, 2],
});
```

Only pass selected props that exist in the current visible columns. Missing props are ignored.

## Save State JSON

Use `serializePivotStateJson` to turn the current Pivot configuration into deterministic JSON:

```ts
const json = serializePivotStateJson(pivot);
localStorage.setItem('sales:pivot-state', json);
```

The JSON is wrapped with a kind and version so the parser can reject unsupported state:

```json
{
  "config": {
    "columns": ["quarter"],
    "rows": ["region", "channel"],
    "values": [{ "aggregator": "sum", "prop": "revenue" }]
  },
  "kind": "revogrid:pivot.state",
  "version": 1
}
```

Use `parsePivotStateJson` to validate and restore it:

```ts
try {
  const saved = localStorage.getItem('sales:pivot-state');

  if (saved) {
    grid.pivot = parsePivotStateJson(saved) as PivotConfig;
  }
} catch (error) {
  console.error('Could not restore Pivot state:', error);
}
```

State JSON is best for saved views, shared report layouts, user preferences, and restoring drill-down state after refresh.

## Practical Example

This example exposes four buttons:

- `CSV`: reads the visible Pivot grid and writes CSV text into the output box.
- `TSV`: reads the visible Pivot grid and writes clipboard-ready TSV into the output box.
- `State JSON`: serializes the current Pivot configuration.
- `Apply JSON`: parses the edited JSON and applies it back to the grid.

The important part is keeping the data export path separate from the state path:

```ts
let pivotConfig: PivotConfig = {
  rows: ['region', 'channel'],
  columns: ['quarter'],
  values: [
    { prop: 'revenue', aggregator: 'sum', label: 'Revenue' },
    { prop: 'orders', aggregator: 'sum', label: 'Orders' },
  ],
};

function showCsv() {
  output.value = exportVisiblePivotToCsv(readGridModel(grid));
}

function showTsv() {
  output.value = buildPivotCopyTsv(readGridModel(grid));
}

function showState() {
  output.value = serializePivotStateJson(pivotConfig);
}

function applyState() {
  pivotConfig = parsePivotStateJson(output.value) as PivotConfig;
  grid.pivot = pivotConfig;
}
```

## Common Mistakes

- Exporting the original source rows instead of the visible grid model. Use `grid.columns`, `grid.source`, and `grid.pinnedBottomSource`.
- Using CSV for copy and paste. TSV usually pastes into spreadsheet cells more reliably.
- Expecting state JSON to contain row data. It stores Pivot configuration, not the source dataset or exported result.
- Applying edited JSON without `try` / `catch`. Invalid JSON, unsupported versions, and invalid field shapes throw errors.
- Forgetting pinned bottom rows. If grand totals are enabled, include `pinnedBottomSource` so totals appear in CSV and TSV output.
- Saving functions in state JSON. State JSON can only contain JSON-safe configuration values; custom runtime callbacks must be restored by application code.

## Next

Continue with [Sorting And Filtering](../sorting-filtering/) or [Field Panel](../field-panel/).
