XLSX Import plugin screenshot
Dark mode ready
No multilingual support
Supports v5.x

XLSX Import by Muhammad Amjad

Community

Lets Filament's own ImportAction read Excel (.xlsx) and OpenDocument (.ods) workbooks as well as CSV, with a sheet picker, while your existing Importer classes, queued jobs and failed-rows downloads keep working unchanged.

Tags: Action Developer Tool
Supported versions:
5.x 4.x
Muhammad Amjad avatar Author: Muhammad Amjad

Package health

Automated checks of this plugin's Composer package

92 / 100
Security 85
Maintenance 100
Ecosystem 100
15 checks
  • Skipped: GitHub Actions pinned to SHA
  • Skipped: GitLab CI includes pinned to SHA
  • Passed: Open security advisories
  • Passed: Dependabot PR responsiveness — No open Dependabot PRs.
  • Skipped: Renovate MR responsiveness
  • Skipped: Dependabot or Renovate configured
  • Skipped: Dependency update cooldown configured
  • Failed: Provides a security policy — View details on Plumb
  • Passed: Abandoned or archived — No consulted source marks the package abandoned (packagist, github).
  • Passed: Commit and release recency — Active: last commit 0 days ago; last release 0 days ago.
  • Passed: composer.lock not committed by library — composer.lock is absent from the released dist archive.
  • Passed: Dist archive is lean
  • Passed: Current Laravel version supported — Package dependencies resolve together with current Laravel 13.0.
  • Passed: Current PHP version supported — Constraint ^8.2 supports current PHP 8.5.
  • Skipped: Current Symfony version supported
Third-party plugin. This is built by the community, not the Filament team. Filament does not review, endorse, or vet the security of plugins outside the filament/ namespace. Review the source and install at your own risk. Found malware or an unresolved security issue the author won't address? Report it .
Powered by Plumb Last scanned 4 days ago

Documentation

XLSX Import: Excel files in Filament's own ImportAction

Filament's ImportAction reads CSV files only. This plugin is a drop-in replacement that also reads Excel (.xlsx) and OpenDocument (.ods) workbooks, with a sheet picker. Your existing Importer classes, queued jobs, completion notifications and the failed-rows download keep working exactly as before. It works with Filament 4 and 5, and adds no dependencies: it reads workbooks with openspout, which Filament already installs.

Latest Version PHP Version License

The import modal with an .xlsx file, the sheet picker and the guessed column mapping

#What it does

  • Accepts .xlsx, .ods and .csv in the same upload field. CSV files go through core's own reader, unchanged.
  • Shows a Sheet select when a workbook has more than one visible sheet. It starts on the sheet whose headings match your Importer's columns best, so a cover or notes sheet is passed over (on a tie, the sheet the workbook opens on). Picking another sheet re-guesses the column mapping. Hidden sheets are not offered.
  • Guesses the column mapping from the header row the same way core does (ImportColumn::guess() works as before).
  • Hands each row to your Importer as strings, the way the same column would arrive from a CSV file:
    • dates as Y-m-d, date-times as Y-m-d H:i:s, times as H:i:s (all configurable);
    • whole numbers without a decimal point (1500, not 1500.0), long numbers without scientific notation (1234567890123), and decimals to Excel's own 15 digits (0.3, not 0.30000000000000004);
    • TRUE/FALSE as 1/0; formulas as their last calculated value; error cells (#N/A) as empty.
  • Skips empty rows, ignores columns with no heading, and numbers repeated headings (Name, Name (2)).
  • Reads the workbook as a stream, row by row, instead of loading the whole file. Rows are chunked and dispatched by core's ImportDispatcher, so queued imports, chunkSize(), maxRows() and job batches behave as with CSV.
  • "Download example" gives an .xlsx file built from your Importer's columns and examples (or a CSV file like core's, if you prefer).
  • Turns away old binary .xls files with a message that says how to save them as .xlsx.

#Requirements

  • PHP 8.2+
  • Filament 4 or 5, on Laravel 12 or 13
  • The PHP zip extension (openspout already needs it)

#Installation

composer require amjadiqbal/filament-xlsx-import

That's all. If you haven't used imports before, set them up as Filament's docs describe (the imports, failed_import_rows, job_batches and notifications tables).

#Usage

Swap ImportAction for XlsxImportAction. Everything you already chain on it still works.

use AmjadIqbal\FilamentXlsxImport\Actions\XlsxImportAction;
use App\Filament\Imports\ProductImporter;

protected function getHeaderActions(): array
{
    return [
        XlsxImportAction::make()
            ->importer(ProductImporter::class),
    ];
}

The same works in a table's headerActions() or toolbarActions(), since Filament 4 and 5 use one action class everywhere.

#Options

XlsxImportAction::make()
    ->importer(ProductImporter::class)

    // Always read this sheet (by name, or index from 0) and hide the sheet picker.
    ->sheet('Products')

    // Or never show the picker: the best-matching sheet is read.
    ->sheetPicker(false)

    // The row that holds the headings, counted from 0 over every row of the sheet, empty ones included
    // (core's own option): headerOffset(2) reads the headings from spreadsheet row 3.
    ->headerOffset(2)

    // How date, date-time and time cells reach your Importer.
    ->dateFormat('d/m/Y')
    ->dateTimeFormat('d/m/Y H:i')
    ->timeFormat('H:i')

    // Workbooks only, or no .ods.
    ->acceptCsv(false)
    ->acceptOds(false)

    // Offer a CSV example file, like core's, instead of .xlsx.
    ->exampleFormat('csv')

    // Seconds the import request may run while it reads a workbook (default 300, only if PHP's limit is lower).
    // null leaves max_execution_time alone.
    ->timeLimit(600)

    // Core's own options work as usual.
    ->chunkSize(500)
    ->maxRows(50_000)
    ->fileRules(['max:20480']);

#Dates in your Importer

A date cell arrives as 2026-01-31, so a rule like date or date_format:Y-m-d and a cast like castStateUsing(fn (string $state) => Carbon::parse($state)) work without guessing. A date typed as text in the spreadsheet arrives exactly as typed, as it would from a CSV.

#Good to know

  • Failed rows are still downloaded as CSV, from core's own route.
  • Queued imports read the file once, in the request that starts the import, and queue the rows (as core does for CSV). Workers don't need access to the uploaded file.
  • Large workbooks: an .xlsx is a zipped XML file, so it reads much slower than a CSV of the same size. On a heavily loaded test machine, a 100,000-row workbook took 37 to 59 seconds to start importing. When the import starts, the data rows are read once, as a stream, into a temporary file, and the request's PHP time limit is raised to timeLimit() (300 seconds by default). Core's ImportDispatcher then builds every chunk's job in that request, as it does for CSV, so the request's memory still grows with the row count. A web server timeout (for example nginx's fastcgi_read_timeout) still applies.
  • While you map columns, each change re-reads the sheet list and the header rows (not the data rows).
  • Remote disks: if Livewire keeps temporary uploads on S3 or another remote disk, the workbook is copied to the local temp directory while it is read, because a workbook is a zip archive that has to be seekable. The copy is removed when the import starts.
  • .ods FALSE cells: openspout 4 reads a FALSE cell in an .ods file as true. This plugin corrects it before reading, so FALSE arrives as 0.
  • Old .xls files (Excel 97-2003) are not supported. openspout can't read them.

#Coming from eightynine/filament-excel-import?

That package imports through Laravel Excel import classes. This one uses Filament's own Importer classes (php artisan make:filament-importer), so validation, failed rows and notifications come from Filament. Move the column logic from your import class into an Importer, then use XlsxImportAction.

#Testing

composer test

#Support

  • 🐛 Bug or feature request: open an issue
  • 🔒 Security issue: please report it privately through GitHub's security tab

#Need this customised, or something built?

I'm available for custom development, package integration, and technical consulting.

Hire me on Upwork

#More packages

This is part of a family of open-source packages. See all of them.

filament-deleted-records A recycle bin for Filament: preview, restore or purge deleted records
filament-change-requests Hold record edits in Filament for approval, with a field-by-field diff
filament-url-image-uploader Upload images to Filament from a URL

#Credits

#License

The MIT License (MIT). See LICENSE.md.

The author

Muhammad Amjad avatar Author: Muhammad Amjad

I am a seasoned full-stack web developer specializing in Laravel, Livewire, and Vue.js ecosystems. With extensive experience in building modern web applications, I leverage the power of Laravel's elegant syntax and robust features to create scalable backend solutions. My expertise extends to crafting responsive and interactive user interfaces using Livewire and Vue.js, enhanced by the utility-first approach of Tailwind CSS.

Plugins
12
Stars
42

From the same author

Record Settings plugin thumbnail

Record Settings

Edit per-user, per-team and per-tenant settings in Filament from a settings page, a modal action or resource form fields, stored with glorand/laravel-model-settings or in a JSON column.

Muhammad Amjad avatar Author: Muhammad Amjad
92 / 100 package health score out of 100
2 stars
Recently added: New Tag: Panels More tags: +2
Dark mode ready No multilingual support
Free
Get it now
Uptime Monitor plugin thumbnail

Uptime Monitor

An admin UI for spatie/laravel-uptime-monitor that lets you add, edit, turn on and off and check uptime and SSL certificate monitors from your Filament panel, with status filters and a dashboard widget.

Muhammad Amjad avatar Author: Muhammad Amjad
92 / 100 package health score out of 100
1 star
Recently added: New Tag: Panels More tags: +2
Dark mode ready No multilingual support
Free
Get it now
Stat Cards plugin thumbnail

Stat Cards

Richer stat cards for the Filament stats overview widget, adding progress bars, icon tiles, background, label and value colours, trends, badges and bar charts to the widget you already have.

Muhammad Amjad avatar Author: Muhammad Amjad
92 / 100 package health score out of 100
1 star
Recently added: New Tag: Widget
Dark mode ready No multilingual support
Free
Get it now
Billing Console plugin thumbnail

Billing Console

A free, read-only billing console for Laravel Cashier (Stripe) that shows your customers, subscriptions, invoices and payments, with an MRR and churn summary, "Open in Stripe" links and a safe "Sync from Stripe" action, inside your Filament panel.

Muhammad Amjad avatar Author: Muhammad Amjad
92 / 100 package health score out of 100
1 star
Recently added: New Tag: Panels More tags: +1
Dark mode ready No multilingual support
Free
Get it now