How to export Gravity Forms entries to CSV, Excel, or PDF
A complete walkthrough for exporting Gravity Tables data, file formats compared, filter behaviour, large-dataset handling, security, and the gotchas that come up when exports go out the door.
Exports are how Gravity Forms data leaves WordPress. They land in finance reports, in compliance audits, in customer email replies, and in client-share folders. Getting them right matters more than most teams realise.
This guide covers the entire export surface in Gravity Tables: which formats, how filters interact, how to handle 50,000-row datasets, and the security rails that keep exports from leaking.
TL;DR#
Add export to your shortcode:
[gravity_table id="42" export="csv,excel,pdf"]
Three formats, three buttons in the toolbar, all respect active filters. Read on for the configuration most production sites end up with.
What each format is good for#
| Format | File | Best for | Avoid for |
|---|---|---|---|
| CSV | .csv | Importing into spreadsheets, BI tools, Excel pivots | Long text fields with newlines (escapes carefully but parsers vary) |
| Excel | .xlsx | Sharing with non-technical stakeholders, formatted reports, charts in the same file | Files >50,000 rows (memory) |
.pdf | Compliance reports, customer-facing receipts, archival | Editing later (locked once generated) |
All three are generated server-side as of v3.5.3, no browser-print workarounds, no .xls-as-HTML hacks, no popup-blocker interference.
Filter-respecting exports#
The single most common misconfiguration in older table plugins: exports ignore active filters. User filters to “Active customers in February”, clicks Export, gets all 12,000 customers across all time.
In Gravity Tables, exports respect:
- All active column filters (date ranges, multi-selects, range sliders)
- The current search query
- The current sort order
- The user’s per-row visibility (
filter_by_user="true"users export only their own rows, server-enforced)
Translation: the file the user downloads matches the table they were looking at. No more, no less.
Per-format toolbar configuration#
The export parameter accepts a comma list. Each format becomes a button:
[gravity_table id="42" export="csv"]
[gravity_table id="42" export="csv,excel"]
[gravity_table id="42" export="csv,excel,pdf"]
To omit the export toolbar entirely, leave export off (default).
To show only the formats relevant to specific roles:
[gravity_table id="42" export="csv,pdf" export_permissions="excel:manager"]
That gives everyone CSV + PDF. The Excel button appears only for users with the manager capability. Server-side enforced, direct AJAX requests for excel from non-managers return 403.
Handling large datasets#
Up to about 5,000 rows, exports complete in well under a second on commodity hosting. Above that, three things kick in:
- Server-side queue, exports >5,000 rows are queued, run in the background, and emailed as a download link when ready
- Memory-efficient row streaming, the export handler streams rows from the database to the file rather than loading all into memory (50,000-row exports stay under 50MB heap)
- Progress indicator, the UI shows a spinner with row count: “Exporting 24,000 of 50,000…”
Configure the queue threshold:
[gravity_table id="big-table" export="csv,excel" export_queue_threshold="2000"]
Or send the file directly to email regardless of size:
[gravity_table id="..." export="csv" export_delivery="email"]
CSV-specific gotchas#
Formula injection#
A = at the start of a cell value can be interpreted as a formula by Excel/Google Sheets. If the value is =cmd|"/c calc"!A0, opening the CSV can execute code in some configurations. This is a real attack vector in user-generated data.
Gravity Tables auto-prefixes any cell starting with =, +, -, @ with a single quote (') on CSV export. Excel renders the value but doesn’t evaluate the formula. Other formats (Excel, PDF) don’t have this concern.
Newlines in cells#
Long-form text fields (textarea entries) often contain newlines. CSV’s RFC 4180 says wrap them in double quotes, which Gravity Tables does, but some downstream tools (older Excel, naive scripts) still struggle. If your data is heavy on long text, prefer Excel or PDF.
UTF-8 BOM#
Excel on Windows assumes Latin-1 unless the file starts with a UTF-8 BOM. Gravity Tables prepends the BOM (EF BB BF) on CSV export so emoji, accented characters, and non-Latin scripts open correctly without manual encoding fixes.
Excel-specific features#
The .xlsx export uses the OpenXML format (real Excel, not HTML-renamed). It includes:
- Frozen header row, scroll the data, keep the column labels visible
- Auto-fit column widths, based on content length, capped at 60 chars
- Number formatting, currency columns get currency format, dates get date format, percentages get percentage format
- Conditional formatting, preserved from any conditional rules set on the table
The output file opens cleanly in Excel, Google Sheets, LibreOffice, and Numbers.
PDF-specific features#
The PDF export uses an embedded HTML-to-PDF pipeline. It includes:
- Page numbers, bottom-right of every page
- Repeating header row, the table header appears at the top of every page in multi-page exports
- Print-optimised typography, switches to a serif body font for readability at small sizes
- Brand header, site logo + table name + export timestamp
- Cover page (optional), set
pdf_cover="true"to include a one-page cover with table metadata
For multi-thousand-row tables, PDF generation can take 10-30 seconds. The queue system kicks in automatically.
Audit trail for exports#
Compliance-sensitive deployments enable export logging:
[gravity_table id="..." export="csv,pdf" audit_exports="true"]
Every export logs:
user_id,user_login,ip_addressformat(csv/excel/pdf)row_count(post-filter)filter_state_json, exact filter configuration at export timetimestamp(UTC)file_hash(SHA-256 of the generated file)
Useful when “who exported this” matters more than “who has access”. The log lives in wp_gt_export_audit and exports via the same /wp-json/gt/v1/export-audit endpoint.
Security: temporary file handling#
Exported files live briefly in wp-content/uploads/gt-exports/ with .htaccess protection that:
- Denies direct access (no path-guessing)
- Returns 403 for any HTTP request
- Allows reads only via the Gravity Tables download endpoint (which enforces nonce + capability checks)
Files are auto-deleted by a daily cron after 24 hours. To shorten:
[gravity_table id="..." export="csv" export_ttl="3600"]
That deletes generated files after 1 hour instead of 24.
Quick recipes#
Customer portal, they download their own data:
[gravity_table id="orders" filter_by_user="true" export="csv,pdf"]
Internal staff dashboard, full export power:
[gravity_table id="all-orders" export="csv,excel,pdf" allowed_roles="staff,manager" audit_exports="true"]
Compliance-sensitive (healthcare, finance):
[gravity_table id="intake" export="csv" export_permissions="csv:compliance" audit_exports="true" export_ttl="3600"]
Large enterprise dataset:
[gravity_table id="..." export="csv" export_queue_threshold="1000" export_delivery="email"]
What this replaces#
Without server-side exports respecting filters, the production pattern was:
- User filters the table
- Clicks “Print” or browser-prints to PDF (loses formatting, breaks columns)
- Or copy-pastes into Excel (loses types, escapes wrong)
- Or asks IT for a database export (manual, slow, includes everything)
export="csv,excel,pdf" collapses all of those into one toolbar, and respects the filters, audit trail, and permissions you’ve already configured.
Related guides#
- How to show users only their own entries, combine with exports for self-serve data download
- How to add inline editing, exports happen after edits, capturing the current state
- v3.5.3 release notes, export overhaul context (real .xlsx, server-side processing)