CSV export
Because grid cells are aggregates, “export” means three different things — and the engine serializes
all of them so the CSV always matches what the math produced. Export the raw source rows behind a
selection, the aggregated roll-up tree exactly as shown (filter + sort + top-N applied), or a
pivot cross-tab flattened to columns. Values ship as raw numerics (machine-readable) by default,
or formatted ($420.00, 45%) to match the display. The built-in Export button below emits the
selection-or-all CSV.
from dash import dcc, html, Input, Output, callbackfrom dash_tensor_grid import build_gridfrom dash_tensor_grid.engine import GridDataEngine
engine = GridDataEngine(sales)payload = build_grid(sales, {"rows": ["region", "country"], "measures": {"revenue": "sum"}})
layout = html.Div([ # ...TensorGrid(...), html.Button("Export", id="export"), dcc.Download(id="download"),])
@callback(Output("download", "data"), Input("export", "n_clicks"), prevent_initial_call=True)def export(_): csv = engine.to_csv() # SOURCE rows (raw frame) # csv = engine.tree_to_csv(payload["row_data"], # AGGREGATED tree as shown # ["region", "country"], ["revenue"]) # pv = build_grid(sales, {"rows": ["region"], "columns": ["category"], # "measures": {"revenue": "sum"}}) # csv = engine.pivot_to_csv(pv, ["region"]) # PIVOT cross-tab, flattened return dcc.send_string(csv, "export.csv")<TensorGrid data={data} rows={['region', 'country']} measures={{ revenue: 'sum' }} showExportButton exportMode="aggregated" // 'source' (raw underlying rows) | 'aggregated' (the roll-up as shown) exportFormatted // emit '$420.00' etc. instead of raw numerics onExport={(csv) => downloadCsv(csv)}/>;
// …or build the CSV yourself from the core helpers:// import { toCsv, treeToCsv, pivotToCsv } from '@tensorgrid/core';<TensorGrid :data="data" :rows="['region', 'country']" :measures="{ revenue: 'sum' }" show-export-button export-mode="aggregated" export-formatted :on-export="downloadCsv"/>import { mountTensorGrid, mountTensorPivot } from '@tensorgrid/vanilla';
const grid = mountTensorGrid(el, { data, rows: ['region', 'country'], measures: { revenue: 'sum' }, showExportButton: true, exportMode: 'aggregated', // 'source' | 'aggregated' exportFormatted: true, onExport: (csv) => downloadCsv(csv),});
grid.exportCsv(); // SOURCE rows (selection-or-all), on demandgrid.aggregatedToCsv({ format: true }); // the AGGREGATED roll-up, formatted
// PIVOT cross-tab: the pivot handle flattens the CURRENT cross-tab to CSV.const pivot = mountTensorPivot(el, { data, rows: ['region'], cols: ['category'], measures: { revenue: 'sum' },});pivot.toCsv();Options
Section titled “Options”- Source vs aggregated vs pivot.
exportMode: 'source'(default) emits the raw underlying rows under the selection, or all rows if none is selected (corerowsForSelection+toCsv, engineto_csv).'aggregated'emits the roll-up tree as shown — filter, sort, and top-N applied (coretreeToCsv, enginetree_to_csv). A pivot flattens its cross-tab to one column per row dimension plus one per measure leaf (corepivotToCsv, enginepivot_to_csv). exportFormatted— withexportMode: 'aggregated', render each measure through itsformatStr($420.00,45%) instead of raw numerics. Ignored for'source'export.- The engine owns serialization. The JS
toCsv/treeToCsv/pivotToCsvare parity-verified ports of Polarswrite_csv(RFC-4180 quoting,null→ empty field), so a Dash export and a React/Vue/Vanilla export of the same view are byte-identical. - Combine with aggregation or a pivot to decide what
the exported view contains, and turn on
exportFormattedwhen the CSV should read like the on-screen table.