Define what all means
An export button becomes ambiguous as soon as a grid loads data on demand. All rows might mean visible rows, selected rows, cached rows, every filtered record or the entire underlying table. These are different products. Define the intended scope before choosing an export API, and display that scope near the action. Users should not discover that an apparently complete report contains only the records they happened to scroll past.
A reliable export is a data operation with a file as its output. The current viewport is usually an incomplete description of that operation. Capture the authoritative filter, sort order, selected identifiers or selection rule, requested columns and data version. The grid can supply part of this state, but the service must decide which records and fields the user is allowed to receive.
Separate the export contract from the screen
Use a versioned export request rather than serializing the complete internal state of the component. A request can identify a saved query, include normalized filters and choose an approved output profile. Validate it independently of the browser. Hidden columns and disabled buttons are interface choices; they are not access controls for a report endpoint.
Decide how selection interacts with filters. Does select all mean every match, or just the current page? What happens when a user selects all matching records and then excludes two? Representing this as a query plus excluded identifiers may be appropriate, but it requires a defined snapshot and clear authorization checks. A list of currently mounted rows cannot express the same intention.
Specify sorting with a deterministic tie-breaker. If thousands of records share a date, date alone may not define a stable order between chunks. Add an agreed unique key where appropriate. This matters when jobs paginate through a service and when users compare two exports. A consistent order makes reconciliation easier even when row ordering is not itself a business requirement.
Choose where the file is built
Client-side generation can be convenient for small, fully loaded datasets. It can preserve immediate local edits and avoid a separate reporting service. Its practical limits include browser memory, serialization work and responsiveness during generation. Measure the actual application with the output options users need. A plain file with a few columns is not equivalent to a styled workbook with formulas and multiple sheets.
Server-side generation is a stronger candidate when the authoritative dataset is remote, the result is large or the report requires a consistent snapshot. A job can read data in bounded batches and expose progress without requiring the browser to retain every record. This creates operational responsibilities: queue limits, cancellation, storage, expiry, monitoring and recovery from interrupted downloads.
A hybrid design also needs a clear boundary. The browser might export a small selection immediately and route larger requests to a job. Use a documented threshold and preserve the same data semantics in both paths. Otherwise, changing the size of a report can unexpectedly change date formatting, permissions or the treatment of unsaved edits.
A million rows is already a format decision
Microsoft documents a worksheet limit of 1,048,576 rows and 16,384 columns. [1] A header uses one of those rows. A five-million-record dataset therefore cannot be placed into a single ordinary worksheet as one record per row. Splitting sheets or files is possible, but the result needs clear boundaries and a way to confirm completeness.
The best output may be an aggregated workbook for people and a separate machine-readable extract for downstream processing. Ask how recipients use the file. If they immediately import it into another database, spreadsheet styling may add cost without value. If they review totals and exceptions, an enormous raw workbook may be less useful than a concise, auditable report with drill-through references.
Do not treat CSV as a universal escape hatch. It has no native field types, and consumers may interpret identifiers, dates or leading zeros differently. Define delimiter, encoding, quoting and line endings. Validate the file with the actual receiving tool. A successful download says nothing about whether an account number survived import unchanged.
What the supplied export data shows
| Grid and version | 100k rows | 1M rows | 5M rows |
|---|---|---|---|
| FastGrid 3.2 | 2,700 ms | 28,500 ms | – |
| AG Grid 36.1 | 2,800 ms | C, crash | – |
| Tabulator 6.5 | 6,500 ms | F, fail | – |
The supplied September 2026 snapshot records plain export at 100,000 rows as 2,700 ms for FastGrid 3.2, 2,800 ms for AG Grid 36.1 and 6,500 ms for Tabulator 6.5. At one million rows, it records 28,500 ms for FastGrid, a crash code for AG Grid and a failure code for Tabulator. These are illustrative entries, not a complete product ranking or a fresh reproduction. Inspect supplied results
At five million rows, those plain-export fields contain a dash, meaning not applicable or not measured in the supplied setup. They do not establish successful five-million-row export for any of these examples. The dataset also separates plain export from tree export and printing. Do not substitute a successful creation time for missing export evidence, or assume printing exercises the same path as workbook generation.
The 100,000-row difference between 2,700 and 2,800 ms should not be presented as a decisive real-world advantage. The methodology selects relatively fast observations, rounds values and does not provide raw distributions. Without repeated comparable samples, uncertainty is unknown. The more actionable observation is that scale and operation type change both duration and completion status.
Preserve meaning across the boundary
An export must specify whether values are raw, formatted or calculated. Currency text that looks correct in the grid may be inconvenient for spreadsheet arithmetic. Conversely, a raw decimal without currency or unit metadata can be misleading. Include units, time zones and the meaning of null values in an accompanying sheet or documented schema.
Local edits introduce another decision. Exporting the server snapshot may omit changes visible in the browser, while exporting local state may include unvalidated edits. Choose deliberately and tell the user. For a regulated or audited workflow, consider requiring successful save before generating the report. For exploratory work, an explicitly labelled draft export may be more appropriate.
Treat untrusted values as data in the chosen format. Spreadsheet applications can interpret certain text as formulas. MUI's export documentation, for example, describes formula escaping and configurable row selection. [2] Verify the protection in your actual exporter and receiving application. Do not disable a protective default simply to make one test fixture look cleaner.
Make long jobs observable
Return a job identifier and a state that distinguishes queued, running, completed, cancelled and failed. Progress should reflect work the system can measure. If the total row count is expensive or unstable, an indeterminate progress indicator is more honest than a fabricated percentage. Keep the interface usable while generation continues.
Design cancellation through the entire pipeline. Closing a progress dialog should not merely hide an expensive job that continues reading data and writing a file. Decide whether cancellation stops the job immediately, after the current batch or only before a final stage. Record the behavior so support staff can explain resource use and users can retry safely.
Define download retention and authorization at retrieval time. A report may contain data that should not become accessible through a permanent public link. Apply the application's actual security requirements to file storage and delivery. Include an expiry message, and make a retry create a new authorized request when necessary rather than silently extending access forever.
Reconcile a report with its source
Choose a small set of independently verifiable checks before testing a large export. Count distinct record identifiers, compare approved aggregate totals and inspect boundary records around every chunk or worksheet transition. A matching row count alone cannot detect one omitted record replaced by a duplicate. Use more than one invariant so the validation is difficult to pass accidentally.
For a changing dataset, record the consistency policy. A report can represent a fixed snapshot, a query executed over a stated interval or another explicitly defined view. What matters is that the implementation and user-facing description agree. If the source cannot provide snapshot consistency, disclose that limitation instead of presenting the file as an exact historical state.
Retain the query definition and verification result with the job metadata for the period the organization requires. This gives support a way to investigate a reported discrepancy without relying on a user's recollection of the grid's filters.
Verify completeness and recoverability
Build a fixture with known row counts, duplicate sort keys, nulls, Unicode and values that resemble formulas. Export it through every supported path. Parse the result independently and check identifiers, column types, totals and ordering. For chunked jobs, introduce a controlled failure between chunks and verify that recovery does not duplicate or omit records.
Include a manifest for large multi-file outputs. It can state the query, generation time, schema version, row count per file and checksum. Avoid including sensitive filter values in filenames or logs unnecessarily. The manifest makes the result inspectable without pretending that a spreadsheet file alone documents the business meaning of the report.
Finally, measure the complete journey: request, queue delay, query, serialization, storage and download. Keep browser generation time separate from end-to-end delivery time. A user choosing between two implementations needs to know whether the difference comes from the grid, the service or the network. The most defensible export feature is the one whose scope, contents and failure behavior remain clear even when only a fraction of the data was ever displayed.