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
Simple Excel

Simple Excel Laravel Package

spatie/simple-excel

Spatie Simple Excel lets Laravel/PHP apps read and write simple Excel and CSV files with low memory usage via generators. It streams rows as LazyCollections, making large imports and exports easy and efficient.

View on GitHub
Deep Wiki
Context7

spatie/simple-excel is a lightweight Laravel/PHP package for reading and writing simple Excel (.xlsx) and CSV files. It uses generators behind the scenes, so memory usage stays low even when processing large files—ideal for imports, exports, and data migrations.

  • LazyCollections for streaming rows without loading entire files into memory
  • Automatic format detection based on file extension (.csv or .xlsx)
  • Read files as associative arrays using the header row as keys
  • Write Excel and CSV files through a fluent, chainable API
  • Laravel-friendly integration with minimal configuration
Frequently asked questions about Simple Excel
How do I install spatie/simple-excel in a Laravel application?
Install it with a single command: composer require spatie/simple-excel. There is no service provider, config file, migration, or published asset to deal with, so nothing needs registering in your app. Because the package depends on illuminate/support, it is already aligned with a standard Laravel install. You can have a working import or export in about five lines of code.
Does spatie/simple-excel use a lot of memory when reading large Excel files?
No, memory usage stays flat regardless of file size. Reading is built on generators, and getRows() returns an Illuminate\Support\LazyCollection, so rows are streamed one at a time instead of being loaded into an array. Calling each() or chunking through the LazyCollection processes millions of rows without exhausting memory. This is the main reason to choose it over loading a whole sheet into a Collection.
What file formats does spatie/simple-excel support?
Only .csv and .xlsx, and the format is auto-detected from the file extension passed to SimpleExcelReader::create() or SimpleExcelWriter::create(). There is no .xls or .ods path in the documented reader and writer factories, and no multi-sheet writing story. It is also not a formatting engine, so charts, pivot tables, and cell styling are out of scope. If you need those, reach for the underlying OpenSpout package or PhpSpreadsheet directly.
Why is my written xlsx file empty or only partially written?
Writes are finalized lazily: an .xlsx file does not get flushed to disk until the writer instance is garbage collected. In long-running workers, Laravel Octane, or queued jobs where the object stays referenced, that can silently produce an empty or truncated file. Call close() explicitly, ideally in a finally block, as a mandatory coding convention. Also be aware there is no atomicity: a crash or timeout mid-write leaves a corrupt file that still looks valid by name, so write to a temp path and rename if that matters.
How do I convert imported headers to snake_case or skip the header row?
The package ships a header toolkit that removes most import boilerplate: trimHeaderRow(), headersToSnakeCase(), formatHeadersUsing(), headerOnRow(), useHeaders(), and noHeaderRow(). There are matching value helpers, trimValues() and formatValuesUsing(), for cleaning cell contents. Combined, these replace the manual array mapping most teams hand-roll around fgetcsv. Note that duplicate header names collapse silently into a single key, with no warning.
Can I stream an Excel or CSV download from a Laravel controller?
Yes, the writer exposes a streamDownload() method that maps onto Laravel's StreamedResponse. Rows are pushed to the browser as they are generated, so the file never has to be buffered to disk first. That makes it a good fit for large exports and memory-constrained containers. Remember to keep the response generation inside the streaming callback so LazyCollection semantics are preserved.
Why are dates or leading zeros wrong when reading an xlsx file?
Type coercion is silent and depends on both the source cell format and the file type. Date cells come back as DateTimeImmutable by default, and you opt into formatted strings with preserveDateTimeFormatting(). Numeric cells in .xlsx arrive as PHP numbers, so an identifier like 007123 loses its leading zeros unless the column is text-formatted in the source. CSVs are string-oriented, so the same data as .xlsx and as .csv can yield different PHP types, meaning any schema contract must be defined per format.
Can I use spatie/simple-excel outside of Laravel?
Technically yes, but it is not clean. The package has a hard dependency on illuminate/support because getRows() returns an Illuminate\Support\LazyCollection, so a non-Laravel service would have to pull in the Collections package. Inside a Laravel codebase that same dependency is a strength: first-class fit, generator-backed iteration, and constant memory. If you are building framework-agnostic code, use openspout or PhpSpreadsheet directly instead.
Is it safe to read Excel files uploaded by users with this package?
The package documents nothing about hardening untrusted input, so treat that responsibility as yours. An .xlsx is a ZIP of XML, which means decompression-bomb and entity-expansion risks are inherited from the parsing layer upstream. Enforce upload size limits, memory_limit, max_execution_time, and temp-disk capacity at the application level before the reader ever touches the file. Validate the detected extension yourself rather than trusting the client-supplied filename.
Can I drop down to OpenSpout if the wrapper does not cover my use case?
Yes, getReader() exposes the underlying OpenSpout\Reader\ReaderInterface, so the facade is not a ceiling. Anything the fluent API does not handle, such as less common reader options, can be done directly against OpenSpout on the same object. That escape hatch significantly lowers lock-in risk. Just keep in mind the package is a thin ergonomic adapter, not an Excel engine, so the underlying library's limits apply.
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.
flareia/php-sdk
mrclay/userland-session
leafs/anchor
leafs/alchemy
leafs/password
leafs/session
leafs/date
leafs/http
leafs/form
actengage/metrics
roundly-consulting/webhooks-for-laravel
leandrodiogenes02/scribe
ahmednour/laravel-custom-reports
brainstud/file-vault
codingagency/laravel-spam-strike
skyraptor/sweet-alert
robinflyhigh/livewire-datatables
rudashi/optima
misakstvanu/laravel-fortify-passkeys
insology/laravel-fatture-in-cloud