Styled Excel and PDF export
Three of the ten export formats need the Enterprise package: excel-list,
excel-pivot and pdf. The other seven — CSV, JSON in three shapes, XML,
print and clipboard — are free.
Everything structural is in the free core: flattening rows, building merged headers, resolving values, evaluating conditional-format rules. What Enterprise adds is the writing — ExcelJS and jsPDF, plus a streaming fallback for large sheets.
Turning it on
Importing anything from the Enterprise package registers the exporter. There is no configuration:
import { EnterprisePivotGrid } from '@kanunilabs/pivotgrid-react-enterprise';
The footer's download menu then enables the three paid entries. From code:
const ref = useRef<PivotGridRef<Sale>>(null);
ref.current?.exportData('excel-pivot', {
fileName: 'Q4-revenue',
applyFilters: true,
expandAll: false,
locale: 'tr-TR',
});
exportData returns a promise, so you can await it and catch a refusal:
try {
await ref.current?.exportData('excel-pivot', { fileName: 'Q4' });
} catch (err) {
// A Community grid refuses the three paid formats. See below.
}
| Option | Default | Read by the exporter |
|---|---|---|
fileName | 'PivotExport' | yes — the extension is appended |
locale | 'tr-TR' | pivot only; the flat list ignores it |
applyFilters | — | yes |
expandAll | — | yes |
signal | — | only at chunk boundaries |
onProgress | — | plumbed, never wired to any UI |
ExportFormat and ExportOptions come from @kanunilabs/pivotgrid-core, not
from the React package.
What this does not do
Size silently changes the file
excel-list past 100,000 rows stops producing a real .xlsx and starts
producing SpreadsheetML with an .xls extension. Same menu item, same name,
different file — and in that format every formatted number is written as a
string, which Excel will not sum.
The pivot equivalent switches at 150,000 materialised cells and additionally drops conditional formatting, outline levels, frozen panes and column widths.
There is no warning at either threshold.
The file will not match the screen
Absent from every export path:
cellTemplateoutput — the exporter writes the underlying value- theme colours
- vertical header merges
dataFieldPosition: 'rows', which the grid honours and the exporters ignore- localized total labels — the screen says "Genel Toplam", the file says "Grand Total". Nothing in the export is translated, although the translations exist.
- conditional rules other than
expression - when several conditional rules match a cell, the screen merges them all; the export applies the first
Progress and cancellation are not reachable from the UI
The footer menu passes neither signal nor onProgress — both are fully
plumbed and wired to nothing. You can only use them through your own ref.
Even then, cancellation is coarse: the signal is polled at chunk boundaries and not during the three most expensive calls, and aborting discards all work.
A wide pivot gets one accommodation: landscape orientation. No page breaking by column, no scaling, no per-column widths.
No font is registered, so non-ASCII text is at risk — worth checking with
Turkish characters before you rely on it, given the default export locale is
tr-TR.
Community refuses, and says so
A Community grid asked for one of the three paid formats gets a rejected
promise naming the format and the package that provides it. The refusal happens
before the exporting event, so nothing is left waiting on it, and the
rejection is routed to your onError handler — or to console.error if you
have none.
Until this shipped it was a console.warn and a resolved promise, fired after
onExporting — so a spinner started on that event span forever with a clean
console.
If your application registers its own exporter under one of those format ids, yours wins: the gate looks for a custom exporter first and steps aside.
It is an edition gate, not a licence gate
An unlicensed Enterprise build still exports — watermarked, not crippled. That is deliberate and matches DataGrid: a dead feature cannot be evaluated before purchase.
What the gate closes is the accidental path. The exporter registers itself into a module-level slot when the Enterprise package is imported, and that slot cannot tell which grid is asking — so one Enterprise import anywhere used to enable styled export for every grid in the bundle, Community ones included. The controller can tell, so the check lives there.
It is not DRM. exportPivotData, PivotExportService and getAdvancedExporter
are public exports of the free package, so deliberate code can still reach the
exporter. Narrowing that is a breaking change and belongs in a major version.