CSV and Excel export
Export the complete view, a selected range, or selected columns from the toolbar, menus, or API.
- React
- Angular
- Core TypeScript
<Grid
rowData={rows}
columnDefs={columns}
rowNumbers
toolbar={{ export: true }}
onGridReady={(api) => {
// api.exportDataAsExcel({ scope: "selection" });
}}
/>
<awb-grid
#grid="awbGrid"
[rowData]="rows"
[columnDefs]="columns"
[rowNumbers]="true"
[toolbar]="{ export: true }"
/>
<button (click)="grid.api?.exportDataAsExcel({ scope: 'selection' })">
Export selection
</button>
const core = new GridCore(measurer, {
columnDefs,
rowNumbers: true,
toolbar: { export: true },
});
api.exportDataAsCsv({ scope: "all" });
api.exportDataAsExcel({ scope: "selection", groupMode: "tree" });
Output fidelity
Excel output is written without runtime dependencies and includes hierarchical headers, cell spans, full-width row merges, pinned panes, typed number/date/ currency values, and application-pinned rows. Aggregate footers become live formulas when an equivalent Excel function exists.
Date cells are written on the local calendar, the day the cell shows. CSV
writes a date column's formatted text (its format, YYYY-MM-DD by default);
when the column's formatter leaves the value unchanged, CSV falls back to the
local YYYY-MM-DD, adding a zone-less local THH:mm:ss only when the value has
a time of day. It never writes a UTC timestamp, which would move a local-midnight
date to the previous day east of Greenwich. Excel receives a real date, and
date-only text such as "2026-03-01" is read as that local day.
Grouped export supports a tree with outline levels and per-group subtotals, or a flat leaf mode with full group paths. Selection export prunes the group tree to relevant rows.
On the server-side row model an export holds the rows the client has fetched, in the shape on screen, and its aggregate cells are the grid's displayed numbers written as values rather than formulas.
Use getDataAsCsv() or getDataAsExcel() when the application needs bytes
without triggering a browser download—for example, to upload or encrypt a file.
Enable export commands
const options = {
allowExportAsCSV: true,
allowExportAsExcel: true,
toolbar: { export: true },
} satisfies GridOptions;
Export is also available from column and body context menus.
Download CSV or Excel
api.exportDataAsCsv({ fileName: "orders.csv" });
api.exportDataAsExcel({ fileName: "orders.xlsx" });
CSV options
These options shape the CSV text only; the Excel export ignores them. They
apply to every CSV path: the download, getDataAsCsv() (which returns exactly
the text the download holds), body and pinned rows, and grouped grids, whose
CSV is the flat list of leaf rows whatever the groupMode.
| Option | Default | Effect |
|---|---|---|
columnSeparator | "," | Text between fields. ";" suits Excel in locales whose decimal mark is a comma; "\t" writes tab-separated values. A field containing the separator is quoted. |
lineEnding | "\n" | Text between rows. RFC 4180 specifies "\r\n", which some strict consumers require. |
includeBom | false | Start the file with a UTF-8 byte order mark. Without it Excel reads the file in the system's legacy code page and garbles non-ASCII text. |
suppressQuotes | false | Never quote fields; the caller guarantees no field contains the separator, a quote or a line break. |
processCellForCsv | (params) => string | undefined: replace a data cell's text. params is { value, formattedValue, data, rowIndex, rowType, column }, the same shape processCellForExcel receives; rowType is "body", "pinnedTop" or "pinnedBottom", and rowIndex counts from 0 within it. Return undefined to keep the grid's text. | |
processHeaderForCsv | ({ column, label }) => string | undefined: replace a header label. On a grouped header, column is the column group for the group row's labels. | |
prependContent / appendContent | Content before the header or after the last row. A string is written verbatim as its own line(s); a 2-D array is written as CSV rows with the export's separator and quoting. |
// Excel in a comma-decimal locale, with accented names intact and card numbers masked.
api.exportDataAsCsv({
fileName: "customers.csv",
columnSeparator: ";",
includeBom: true,
prependContent: [["Customer export", new Date().toLocaleDateString()]],
processCellForCsv: ({ column, formattedValue }) =>
column.colId === "cardNumber" ? `**** ${formattedValue.slice(-4)}` : undefined,
});
Export a range or selected columns
api.exportDataAsCsv({ scope: "selection" });
api.exportDataAsExcel({
scope: "selectedColumns",
columnIds: ["orderNo", "customer", "total"],
includeHeaders: true,
});
Grouped export
api.exportDataAsExcel({ groupMode: "tree" }); // group headers + subtotals
api.exportDataAsExcel({ groupMode: "leaves" }); // flat leaves with group paths
CSV and Excel include application-pinned top and bottom rows around the body.
Group footer rows (groupTotalRow,
grandTotalRow) are not exported as rows: the tree-mode Excel export already
writes a SUBTOTAL per group (and, while aggregates show, a grand-total footer), so the file is the same
with or without them, and CSV writes leaf rows only.
Pivot export
While pivot mode is on, the same commands export the pivot table
itself: the generated nested header over one row per group node (every level,
expanded or not, indented under the group column), with real numbers in the
aggregate cells. Pivot exports are whole-table by design — the range and
selected-column scopes are ignored — and the default filename becomes
grid-pivot.csv / grid-pivot.xlsx. Turn pivot mode off to export the source
rows instead.
Formula injection
A spreadsheet that opens a CSV evaluates any text cell starting with =, +,
-, @, a tab or a carriage return as a formula. The CSV export therefore
writes such text with a leading single quote (=1+1 becomes '=1+1), in body
cells, group and full-width labels, and header labels. Cells written as numbers
(a numeric value, or a numeric value in a NUMBER / CURRENCY column) are left
as they are, so -5 stays -5. The guard is always on, whatever the separator
and even with suppressQuotes. Text returned by processCellForCsv or
processHeaderForCsv, and the cells of a 2-D prependContent / appendContent,
are guarded too; a cell result or extra-content cell that is a plain number such
as -5 is left as it is. A string prependContent / appendContent is the
application's own text and is written verbatim.
The Excel export needs no guard: text is written as string cells, which Excel never evaluates. The only formula cells are the aggregate and subtotal formulas the exporter writes itself.
Get bytes without downloading
const csv = api.getDataAsCsv({ scope: "all" });
await fetch("/exports/orders.csv", { method: "PUT", body: csv });
const bytes = await api.getDataAsExcel();
const workbook = new Blob([bytes], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});