Export - Formatting, scope + XLS
Faithful export: currency / date / percent render as shown (toggle raw values), pick a row scope (view / selected / all), legacy .xls (Excel 2003 XML, no jszip), an exportValue hook, and the drop-in SvExportMenu. (requires @svgrid/enterprise)
A live, editable Svelte 5 data grid example from the SvGrid gallery (Data Export & Import). See the SvGrid documentation for the full API.
About this example
Faithful export from the Svelte 5 data grid. Currency, date and percent values export exactly as shown on screen, with a rawValues toggle for the underlying numbers; a row scope picks the current view, only selected rows or all rows; legacy .xls in Excel 2003 XML format needs no zip library and keeps numbers numeric; an exportValue hook handles a custom-rendered column; and the drop-in SvExportMenu component supplies the format picker, scope and progress.
Showcases the export improvements:
- Faithful values: currency / date / percent export exactly as shown on screen (toggle
rawValuesto see the underlying raw values). - Row scope: export the current view, only selected rows, or all rows.
- Legacy .xls (Excel 2003 XML) for old-Excel compatibility - no jszip needed, and numbers stay numeric.
exportValuehook for a custom-rendered column.- The drop-in <SvExportMenu> component (format picker + scope + progress).
Imports, features and API used
Imports: @svgrid/grid, @svgrid/enterprise, ../shared/seed
Table features registered: rowSortingFeature, columnFilteringFeature, rowSelectionFeature
Columns: company (Company), product (Product), sellDate (Sell date), price (Price), discount (Discount), country (Country), company (Company), product (Product), sellDate (Sell date), price (Price), discount (Discount), orderId (Order)
SvGridApi methods called: api.exportData()
Frequently asked questions
How do I export only the selected rows?
Pass rows: 'selected' to exportData, or pick it in SvExportMenu's scope control. rows: 'all' ignores the current filter, the default 'displayed' exports the view, and an explicit array overrides all three.
When would I use .xls instead of .xlsx?
For consumers on old Excel versions or tools that only read the 2003 XML format. It is written as plain XML, so it needs no zip library, and numeric cells stay numeric.
How do I control a custom column's exported value?
Set exportValue on the column definition. It receives the row and returns the text or number to write, which is how a snippet-rendered column exports something meaningful.
Related documentation
Related articles
- What's New in SvGrid Enterprise - Export, Pivot, Import, Print, and AI - A practical look at @svgrid/enterprise - pivot tables, Excel and PDF export, data import, printing, and an AI assistant. Covers when each feature earns its place and what to watch out for in production.
- Importing CSV into a Svelte Data Grid - Parse a user-uploaded CSV file into objects, map its headers to grid columns, validate rows before committing, and handle the edge cases that actually bite you in production.
- A Date-Picker Cell Editor in SvGrid - How to make date columns editable with a real date picker in SvGrid - including display formatting, time zone handling, and validation that preserves user input.
Source code (201-export-formatting-and-xls.svelte)
<script lang="ts">
/**
* 201. Export: faithful formatting, scope, and legacy XLS (Enterprise)
* -------------------------------------------------------------------
* Showcases the export improvements:
* - Faithful values: currency / date / percent export exactly as shown
* on screen (toggle `rawValues` to see the underlying raw values).
* - Row scope: export the current view, only selected rows, or all rows.
* - Legacy .xls (Excel 2003 XML) for old-Excel compatibility - no jszip
* needed, and numbers stay numeric.
* - `exportValue` hook for a custom-rendered column.
* - The drop-in <SvExportMenu> component (format picker + scope + progress).
*/
import {
SvGrid,
tableFeatures,
rowSortingFeature,
columnFilteringFeature,
rowSelectionFeature,
type GridColumns,
type ConditionalFormat,
type SvGridApi,
} from '@svgrid/grid'
import {
installEnterprise,
SvExportMenu,
type EnterpriseGridApi,
type ExportColumn,
} from '@svgrid/enterprise'
import { makeOrders, type Order } from '../shared/seed'
const features = tableFeatures({
rowSortingFeature,
columnFilteringFeature,
rowSelectionFeature,
})
// Add a synthetic `discount` (0..40 points) so we have a percent column.
type Row = Order & { discount: number }
let rows = $state<Row[]>(makeOrders(200).map((o, i) => ({ ...o, discount: (i * 7) % 40 })))
let api = $state<EnterpriseGridApi<typeof features, Row> | null>(null)
let rawValues = $state(false)
let scope = $state<'displayed' | 'selected' | 'all'>('displayed')
let lastAction = $state('')
let errorMsg = $state<string | null>(null)
// Priced with a real number `format` so the export renders "$1,234.00",
// a percent column stored as 0..100 points, and a formatted date.
const columns: GridColumns<Row> = [
{ field: 'company', header: 'Company', width: 150 },
{ field: 'product', header: 'Product', width: 160 },
{
field: 'sellDate',
header: 'Sell date',
width: 120,
format: { type: 'date', pattern: 'y-m-d' },
},
{
field: 'price',
header: 'Price',
width: 120,
format: { type: 'currency', currency: 'USD' },
},
{
field: 'discount',
header: 'Discount',
width: 110,
format: { type: 'percent', valueIsPercentPoints: true },
},
{ field: 'country', header: 'Country', width: 100 },
]
// Conditional formatting: a color scale on discount + a data bar on price.
// These render on screen AND carry into the pdf / xlsx / html exports.
const conditionalFormats: ConditionalFormat<Row>[] = [
{ type: 'colorScale', columns: ['discount'], min: '#dcfce7', mid: '#fef9c3', max: '#fee2e2' },
{ type: 'dataBar', columns: ['price'], color: '#3b82f6' },
]
// A custom "Order" column whose export value comes from an exportValue hook
// (as if the on-screen cell were a custom snippet the file can't serialize).
const exportColumns: ExportColumn<Row>[] = [
// `link` turns Company into a clickable hyperlink in xls / html / pdf exports.
{ field: 'company', header: 'Company', link: (r) => `https://www.google.com/search?q=${encodeURIComponent(r.company)}` },
{ field: 'product', header: 'Product' },
{ field: 'sellDate', header: 'Sell date', format: { type: 'date', pattern: 'y-m-d' } },
{ field: 'price', header: 'Price', format: { type: 'currency', currency: 'USD' } },
{ field: 'discount', header: 'Discount', format: { type: 'percent', valueIsPercentPoints: true } },
{ field: 'orderId', header: 'Order', exportValue: (r) => `#${r.orderId}` },
]
function onReady(next: SvGridApi<typeof features, Row>) {
api = installEnterprise(next)
}
async function run(label: string, format: 'xlsx' | 'xls' | 'csv' | 'pdf') {
if (!api) return
errorMsg = null
try {
await api.exportData({
format,
filename: 'orders',
columns: exportColumns,
rows: scope,
rawValues,
conditionalFormats,
pageOrientation: 'landscape',
})
lastAction = label
} catch (err) {
errorMsg = err instanceof Error ? err.message : String(err)
}
}
</script>
<section class="flex flex-col flex-1 min-h-0 gap-3">
<div class="ex-lead text-sm shrink-0">
Exports reflect what you see: currency, dates, and percents are formatted.
Toggle <strong>raw values</strong> to export underlying numbers, pick a
<strong>scope</strong>, and try <strong>.xls</strong> for legacy Excel.
</div>
<div class="flex flex-wrap items-center gap-2 shrink-0">
<!-- Drop-in menu: format picker + scope + column picker + copy + progress -->
<SvExportMenu
{api}
filename="orders"
label="Export menu"
formats={['xlsx', 'xls', 'pdf', 'csv', 'json', 'md']}
allowPrint
{conditionalFormats}
/>
<span class="ex-divider mx-1 h-5 w-px"></span>
<!-- Manual buttons wired to the scope + rawValues toggles below -->
<button type="button" class="btn" disabled={!api} onclick={() => run('Excel (.xlsx)', 'xlsx')}>xlsx</button>
<button type="button" class="btn" disabled={!api} onclick={() => run('Excel 97-2003 (.xls)', 'xls')}>xls</button>
<button type="button" class="btn" disabled={!api} onclick={() => run('CSV', 'csv')}>csv</button>
<button type="button" class="btn" disabled={!api} onclick={() => run('PDF', 'pdf')}>pdf</button>
<label class="ex-label flex items-center gap-1.5 text-xs">
Scope
<select bind:value={scope} class="ex-select rounded px-2 py-1 text-xs">
<option value="displayed">Current view</option>
<option value="selected">Selected</option>
<option value="all">All rows</option>
</select>
</label>
<label class="ex-label flex items-center gap-1.5 text-xs">
<input type="checkbox" bind:checked={rawValues} class="h-4 w-4" />
Raw values
</label>
{#if lastAction}
<span class="text-xs text-green-600 dark:text-green-400">Exported {lastAction}</span>
{/if}
{#if errorMsg}
<span class="text-xs text-red-600 dark:text-red-400">{errorMsg}</span>
{/if}
</div>
<div class="flex-1 min-h-0">
<SvGrid responsive={true}
columnResize
data={rows}
columns={columns}
features={features}
conditionalFormats={conditionalFormats}
filterMode="menu"
selectionMode="both"
showRowSelection={true}
showRowNumbers={true}
enableCellSelection={true}
rowHeight={36}
containerHeight="100%"
fitColumns={true}
onApiReady={onReady}
/>
</div>
<footer class="ex-foot text-xs shrink-0">
Enterprise feature. <code>.xls</code> is the Excel 2003 XML Spreadsheet
format - opens in Excel 97-2003+ with no <code>jszip</code> dependency and
keeps numbers numeric. The <code>#Order</code> column uses an
<code>exportValue</code> hook.
</footer>
</section>
<style>
.btn {
border-radius: 0.375rem;
border: 1px solid var(--sg-border, rgb(203 213 225));
padding: 0.375rem 0.75rem;
font-size: 0.875rem;
font-weight: 500;
background: var(--sg-bg, white);
color: var(--sg-fg, rgb(15 23 42));
}
.btn:disabled { opacity: 0.5; }
.ex-lead { color: var(--sg-fg, #475569); }
.ex-foot { color: var(--sg-muted, #64748b); }
.ex-label { color: var(--sg-muted, #475569); }
.ex-divider { background: var(--sg-border, #cbd5e1); }
.ex-select {
border: 1px solid var(--sg-input-border, #cbd5e1);
background: var(--sg-input-bg, #ffffff);
color: var(--sg-fg, #0f172a);
}
</style>More Data Export & Import examples
- Excel / CSV import - File picker + column mapping + per-row validation preview before commit. Reads xlsx / csv / tsv / json with format auto-detect.
- Export + Print - Enterprise feature pack: download to Excel, PDF, CSV, TSV, HTML, or open a printable view in a new window.
- Export - Theme-matched - One xlsx, light or dark - styles read from the same --sg-* tokens the grid renders with.
- Export - Header + Footer + Logo - Branded xlsx: PNG logo + title + subtitle in the page header, generated date + page numbers in the footer.
- Export - Cell images - Product grid with thumbnail column. On xlsx export each thumbnail is embedded as a real picture cell.