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

Product Decisions This Supports

  • Build vs. buy for tabular I/O. Excel/CSV read-write is a commodity capability with a deceptively large edge-case surface (multi-sheet workbooks, header rows, date cells, formulas, stray whitespace, large files). This package replaces a build-it-yourself effort with a MIT-licensed composer require, so the decision is "buy" on almost every dimension — the real budget question becomes how much product-specific import logic we still own.
  • Shipping import features on the roadmap. Unblocks the recurring backlog of "customers want to upload a spreadsheet" and "admins want to export this list" requests: bulk record import, admin data exports, customer-facing report downloads, CSV feeds to partners/accounting, one-off data migration from legacy tools.
  • Large-file viability. getRows() returns a Laravel LazyCollection backed by generators, so memory stays flat instead of loading the file into an array. That's a product-defining detail: it enables "upload a 200MB file" as a supported promise rather than a support ticket. take()/skip() let us preview a file (e.g., "show first 5 rows" before the user confirms the mapping) cheaply.
  • Scope negotiation on import UX. Header manipulation is built in — noHeaderRow(), useHeaders(), headerOnRow(), trimHeaderRow(), headersToSnakeCase(), formatHeadersUsing(), plus trimValues()/formatValuesUsing() for cell cleanup. That means we can promise "we'll cope with messy supplier spreadsheets" without building a normalisation layer from scratch.
  • Export/streaming decisions. SimpleExcelWriter::streamDownload() makes server-side file storage optional — relevant for exports containing PII or tenant data, where "don't persist the file" simplifies retention policy, GDPR scoping, and cleanup cron jobs.
  • Prioritisation input. Because the package exposes getReader() (raw openspout reader), we can defer "we need advanced spreadsheet features" requests and de-risk later by going one layer down — a real option, not a rewrite.
  • Trade-off to record in the roadmap: this is a simple Excel library, not a spreadsheet engine. Anything involving styling, generated charts, pivot tables, macros, or complex formula authoring is explicitly out of scope and should be treated as a separate initiative.

When to Consider This Package

Adopt when:

  • The stack is Laravel/PHP and the need is line-oriented tabular data — rows in, rows out — not spreadsheet document authoring.
  • Files are CSV and/or .xlsx only, and may be large enough that memory behaviour matters.
  • You want multi-sheet reading (select by index or name, getSheetNames(), hasSheet()), formula-value vs. formula-string control (keepFormulas()), or date-cell control (preserveDateTimeFormatting()).
  • You want an opinionated, small API surface over a full spreadsheet toolkit — fewer abstractions for the team to learn, less vendor lock-in.
  • Licensing matters: MIT, no per-seat or per-document cost, no procurement cycle.

Look elsewhere when:

  • Output must be presentable: cell styling, number formats, merged cells, conditional formatting, charts, frozen panes, print layouts → PhpSpreadsheet (or a commercial SDK) on the PHP side, or a dedicated reporting service.
  • You need .xls (legacy binary), password-protected workbooks, or embedded images/objects.
  • You need the library to be the validation layer. It is not: schema validation, type coercion, row-level error reporting, partial-import semantics, deduplication/idempotency, and audit trails are all still ours to build.
  • Customer files are genuinely arbitrary. The docs don't advertise delimiter sniffing or encoding conversion — semicolon-delimited, BOM-prefixed, or Latin-1 exports will need our own handling. Budget for a fixture library of real, ugly customer files before promising "we accept any CSV."
  • Volume is beyond "a file a human uploaded" — continuous, multi-gigabyte, multi-source ingestion is a pipeline problem (queue + object storage + warehouse loader), not a library problem.

Adoption gate before committing: the supplied metadata is noisy — Dependents: 0 and a release date of 2026-10-19 are both implausible and suggest an incomplete data snapshot. Verify the actual latest release, PHP/Laravel version support, and commit activity on Packagist/GitHub directly. The upstream dependency (openspout/spout) is the real engine, so confirm its maintenance posture too. Also note this is a Spatie-maintained package with a support-us model rather than an enterprise SLA — acceptable for a commodity dependency, but worth naming as a risk.

How to Pitch It (Stakeholders)

To executives: We have a steady stream of requests that boil down to "let users upload a spreadsheet" and "let admins download their data." Both normally mean weeks of engineering to handle the file formats safely, and a permanent maintenance tax every time a customer sends a file that breaks our parser. This is a free, MIT-licensed, widely used Laravel package that already solves the format problem, and solves it in a memory-safe way so large uploads don't take the app down. The result: those features ship in days, the licence cost is zero, and we keep our data in our own systems instead of buying a third-party file-processing service. What we still build — and therefore still control — is the part that's actually differentiating: what the columns mean, how we validate them, and what the user sees when a row fails.

To engineering: Small, idiomatic surface on top of openspout: SimpleExcelReader::create($path)->getRows() gives you a LazyCollection, so it's filter/map/each like the rest of Laravel, and memory stays flat on big files. SimpleExcelWriter mirrors it, with streamDownload() for exports. It handles multiple sheets, header offsets, header/value normalisation, formulas, and date cells. It won't style workbooks or read .xls. getReader() is the escape hatch if we outgrow it. Caveat: SimpleExcelWriter finalises .xlsx files on destruct or explicit close() — call close() in queued jobs, or the file won't be there when the next step reads it.

What we own either way (call it out now, not in the retro): delimiter/encoding detection for real-world files, a validation + error-reporting layer with per-row feedback, queueing and progress for big imports, idempotency and duplicate handling, PII retention for exports, and audit logging. Track import success rate and time-to-first-import as the adoption metrics; if those stay healthy, the build-vs-buy call was right.

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.
mattfalahe/seat-discord-pings
szabrob/laravel-barion
inventas/laravel-apple-maps
yazidkhaldi/laravel-ilsawn
kusikusicms/routes
jeffersongoncalves/filament-centrifugo
itshayu/laravel-admin-v1
kduma/webprint-service-cli
jeffersongoncalves/laravel-centrifugo
pushery/ses-inbound-mail-for-laravel
pushery/http-api-for-laravel
flareia/php-sdk
mrclay/userland-session
leafs/anchor
leafs/alchemy
leafs/password
leafs/session
leafs/date
leafs/http
leafs/form