Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Xlsx Export Laravel Package

asignua/filament-xlsx-export

Filament XLSX Export adds fast, customizable Excel (.xlsx) exports to Filament resources and tables. Export filtered or selected records with configurable columns, headers, and formatting, all from a simple admin action.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and publish its config, then wire an export into the Filament table you already have. The shortest path is to add the package's export action to a resource/page and let it derive columns from the table; the first useful export is usually "current table, all matching rows, with a row number and human-readable state."

  1. Require the package and run the install/publish command so config/...php (including the streaming block) exists.
  2. Add the export action/trait to the ListRecords page or resource. Confirm the download works on a small table before customising columns.
  3. Add rowIndex() as the first column if users need spreadsheet row numbers, and formatted() for any column where the table's display string is what people want in the file.
  4. Move on to typed columns (boolean(), dates, numbers) only once the basic export is correct — the typed XLSX writer is where NULL/false and date semantics matter.

Read the column-definition API and the streaming config first; those two areas account for most of the behaviour you will need to change day to day.

Implementation Patterns

Derive columns from the table, override selectively. The default column set is usually right; override per column where the file needs something different from the screen. SelectColumn exports the option label the table shows — good for human-facing reports, but if a downstream system needs the stored value, define a raw column instead.

Use rowIndex() for numbering, not $rowLoop->iteration. rowIndex() numbers the file's rows from 1 regardless of which table page the user was on when they hit export. If you pass $rowLoop into a state closure, that object is counted from the file's first row on any page too — but only rowIndex() compensates for the page offset. Pick one convention per export and stick to it.

Treat the streaming route as the auth boundary. As of v1.0.1 the streaming route switches the default guard to the panel's guard, matching Filament's Authenticate middleware. That means auth(), Gate checks and query scopes written with auth() inside export code see the page's user without extra plumbing. Keep streaming.middleware limited to starting the session; do not re-implement guard switching there.

Guard-aware scopes in export queries. Because auth() resolves correctly in streaming mode, tenant/ownership scopes can be written the same way as in the resource query. For queued exports, remember the job runs outside the request: resolve and pass the user/tenant explicitly rather than relying on auth() at job runtime.

Format dates in date columns, text in formatted(). formatted() output is now treated as text and is no longer parsed back into a date. That removes the day/month swap risk, but it also means a date formatted into a string stays a string in the file. Use real date columns when the spreadsheet needs date semantics (sorting, filtering, date arithmetic).

Handle booleans with the typed column. Use boolean() (and ExportsTypedXlsx) when the file must contain real booleans. SelectColumn plus formatted() is fine for display, but typed booleans are what survive round-trips into other tooling.

Test with realistic page state. Write feature tests that export from page 2+ of a paginated table, with a mix of NULL/false booleans, a select column, a date column, and a filename containing non-ASCII characters. Assert sheet names and cell types, not just that a download was returned.

Multi-panel and guest behaviour. A guest on a table outside any panel stays in Livewire mode rather than receiving a refused streaming link, so public/guest tables degrade gracefully. In multi-panel apps, verify exports from each panel separately — the guard switch is per panel.

Gotchas and Tips

  • NULL is not FALSE in the spreadsheet. A nullable boolean() column reads FALSE for NULL because the core empties NULL before the typed writer sees it. Do not try to distinguish them with formatStateUsing(); the README no longer recommends that because the NULL is already gone. If the distinction matters, encode it explicitly (e.g. a state string or a separate "is set" column).
  • false from CSV core. ExportsTypedXlsx::boolean() writes FALSE for the empty CSV cell the core produces for false. This is fixed in v1.0.1, so pin at least that version if you rely on typed booleans.
  • formatted() is text. It will not be re-parsed as a date, and list state is formatted item by item. Don't route dates through formatted() and expect a date cell; don't rely on the old parse-back behaviour.
  • Reserved sheet names. History is reserved by Excel and becomes History 1. Sanitise dynamic sheet names and don't hard-code assumptions in tests or downstream macros.
  • Non-ASCII filenames. Characters such as ¢ and ½ no longer break downloads in v1.0.1; on older versions, sanitise filenames before export.
  • Row offset confusion. rowIndex() compensates for the page offset; a stdClass $rowLoop received by a state closure does not (it counts from the file's first row). Mixing the two in one export produces numbering that looks off by a page.
  • Don't add auth middleware to the streaming route. The guard switch is handled for you; adding guard logic on top can override the panel guard or break the session-only middleware assumption.
  • Large exports. Streaming keeps request context (and therefore auth()), while queued exports need the user/tenant captured up front. For big tables, prefer queueing and pass identity explicitly rather than discovering the missing auth context in production.
  • Extension points. Column classes and the typed writer are the places to customise; keep custom formatting in column definitions rather than post-processing the downloaded file, or you lose the package's type handling.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource