PHPackages                             rap2hpoutre/fast-excel - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [PDF &amp; Document Generation](/categories/documents)
4. /
5. rap2hpoutre/fast-excel

ActiveLibrary[PDF &amp; Document Generation](/categories/documents)

rap2hpoutre/fast-excel
======================

Fast Excel import/export for Laravel

v5.14.0(2w ago)2.3k27.7M↓46.3%268[5 issues](https://github.com/rap2hpoutre/fast-excel/issues)[5 PRs](https://github.com/rap2hpoutre/fast-excel/pulls)20MITPHPPHP ^8.0CI passing

Since Apr 5Pushed 2w ago25 watchersCompare

[ Source](https://github.com/rap2hpoutre/fast-excel)[ Packagist](https://packagist.org/packages/rap2hpoutre/fast-excel)[ GitHub Sponsors](https://github.com/rap2hpoutre)[ RSS](/packages/rap2hpoutre-fast-excel/feed)WikiDiscussions master Synced 2w ago

READMEChangelog (10)Dependencies (20)Versions (106)Used By (20)

[![](https://user-images.githubusercontent.com/36028424/40173202-9a03d68a-5a03-11e8-9968-6b7e3b4f8a1b.png)](https://user-images.githubusercontent.com/36028424/40173202-9a03d68a-5a03-11e8-9968-6b7e3b4f8a1b.png)

[![Version](https://camo.githubusercontent.com/88690c0753c669bde9c175a8366e801c198e77cb860649f76a50fb1eed6dd515/68747470733a2f2f706f7365722e707567782e6f72672f7261703268706f757472652f666173742d657863656c2f76657273696f6e3f666f726d61743d666c6174)](https://packagist.org/packages/rap2hpoutre/fast-excel)[![License](https://camo.githubusercontent.com/b51908ff8146800b12ffa3c89bf64d99a69d9061e0859ba35f2e9d3bc329cf46/68747470733a2f2f706f7365722e707567782e6f72672f7261703268706f757472652f666173742d657863656c2f6c6963656e73653f666f726d61743d666c6174)](https://packagist.org/packages/rap2hpoutre/fast-excel)[![StyleCI](https://camo.githubusercontent.com/2dcc8622d867639965043425700c8df00523fcc114251721884f3a93d42b5f84/68747470733a2f2f6769746875622e7374796c6563692e696f2f7265706f732f3132383137343830392f736869656c643f6272616e63683d6d6173746572)](https://github.styleci.io/repos/128174809?branch=master)[![Tests](https://github.com/rap2hpoutre/fast-excel/actions/workflows/tests.yml/badge.svg)](https://github.com/rap2hpoutre/fast-excel/actions/workflows/tests.yml)[![Total Downloads](https://camo.githubusercontent.com/6f2e8f59fde016298c7d6bcc8c7a0c6b028b34301b2700980ae6c278e05b3988/68747470733a2f2f706f7365722e707567782e6f72672f7261703268706f757472652f666173742d657863656c2f646f776e6c6f616473)](https://packagist.org/packages/rap2hpoutre/fast-excel)

Fast Excel import/export for Laravel, thanks to [Spout](https://github.com/box/spout). See [benchmarks](#benchmarks) below.

Quick start
-----------

[](#quick-start)

Install via composer:

```
composer require rap2hpoutre/fast-excel

```

Export a Model to `.xlsx` file:

```
use Rap2hpoutre\FastExcel\FastExcel;
use App\User;

// Load users
$users = User::all();

// Export all users
(new FastExcel($users))->export('file.xlsx');
```

Export
------

[](#export)

Export a Model, Query or **Collection**:

```
$list = collect([
    [ 'id' => 1, 'name' => 'Jane' ],
    [ 'id' => 2, 'name' => 'John' ],
]);

// export() returns the absolute path to the written file
$path = (new FastExcel($list))->export('file.xlsx');
```

Export `xlsx`, `ods` and `csv`:

```
$invoices = App\Invoice::orderBy('created_at', 'DESC')->get();
(new FastExcel($invoices))->export('invoices.csv');
```

Export only some attributes specifying columns names:

```
(new FastExcel(User::all()))->export('users.csv', function ($user) {
    return [
        'Email' => $user->email,
        'First Name' => $user->firstname,
        'Last Name' => strtoupper($user->lastname),
    ];
});
```

Hide columns from the exported file while still being able to use them inside the callback, using `hideColumnsPrefixedWith()`. This is handy for callback-only data (lookups, computed flags, etc.) that should not appear as a column:

```
(new FastExcel(User::all()))->hideColumnsPrefixedWith()->export('users.csv', function ($user) {
    return [
        'Name'  => $user->name,
        '_role' => $user->role, // used for logic below, never written to the file
    ];
});
```

Columns are hidden from both the header row and every data row. The prefix defaults to `_`, and any other one can be used — `hideColumnsPrefixedWith('tmp_')`. Hiding is opt-in: unless you call this method, every column is exported, so columns that already start with an underscore keep working as before.

Download (from a controller method):

```
return (new FastExcel(User::all()))->download('file.xlsx');
```

Import
------

[](#import)

`import` returns a Collection:

```
$collection = (new FastExcel)->import('file.xlsx');
```

Import a `csv` with specific delimiter, enclosure characters and "gbk" encoding:

```
$collection = (new FastExcel)->configureCsv(';', '#', 'gbk')->import('file.csv');
```

Import and insert to database:

```
$users = (new FastExcel)->import('file.xlsx', function ($line) {
    return User::create([
        'name' => $line['Name'],
        'email' => $line['Email']
    ]);
});
```

Limit the number of data rows imported with `limitRows` (headers excluded). It works with both `import` and `importLazy`:

```
$collection = (new FastExcel)->limitRows(100)->import('file.xlsx');
```

Facades
-------

[](#facades)

You may use FastExcel with the optional Facade. Add the following line to `config/app.php` under the `aliases` key.

```
'FastExcel' => Rap2hpoutre\FastExcel\Facades\FastExcel::class,
```

Using the Facade, you will not have access to the constructor. You may set your export data using the `data` method.

```
$list = collect([
    [ 'id' => 1, 'name' => 'Jane' ],
    [ 'id' => 2, 'name' => 'John' ],
]);

FastExcel::data($list)->export('file.xlsx');
```

Global helper
-------------

[](#global-helper)

FastExcel provides a convenient global helper to quickly instantiate the FastExcel class anywhere in a Laravel application.

```
$collection = fastexcel()->import('file.xlsx');
fastexcel($collection)->export('file.xlsx');
```

Advanced usage
--------------

[](#advanced-usage)

### Export multiple sheets

[](#export-multiple-sheets)

Export multiple sheets by creating a `SheetCollection`:

```
$sheets = new SheetCollection([
    User::all(),
    Project::all()
]);
(new FastExcel($sheets))->export('file.xlsx');
```

Use index to specify sheet name:

```
$sheets = new SheetCollection([
    'Users' => User::all(),
    'Second sheet' => Project::all()
]);
```

### Import multiple sheets

[](#import-multiple-sheets)

Import multiple sheets by using `importSheets`:

```
$sheets = (new FastExcel)->importSheets('file.xlsx');
```

You can also import a specific sheet by its number:

```
$users = (new FastExcel)->sheet(3)->import('file.xlsx');
```

`sheet()` also accepts a sheet name, so you can select a sheet without knowing its position:

```
$users = (new FastExcel)->sheet('Users')->import('file.xlsx');
```

Import multiple sheets with sheets names:

```
$sheets = (new FastExcel)->withSheetsNames()->importSheets('file.xlsx');
```

Use `withSheetContext()` to receive the current sheet name as the first argument of the `importSheets` callback — handy when the same field names need to be handled differently per sheet:

```
$sheets = (new FastExcel)
    ->withSheetContext()
    ->importSheets('file.xlsx', function ($sheetName, $row) {
        if ($sheetName === 'Users' && empty($row['email'])) {
            return null; // skip rows without an email on the Users sheet
        }

        return $row + ['_sheet' => $sheetName];
    });
```

### Export large collections (low memory)

[](#export-large-collections-low-memory)

Passing a materialized collection (`User::all()`, `->get()`, `collect([...])`) loads every row into memory *before* the export starts, so it grows with the size of the data and a large enough dataset fails outright with `Allowed memory size of N bytes exhausted`. Feed a lazy source instead and peak memory stays flat, whatever the row count.

Eloquent's `cursor()` (or `->lazy()`) returns a [`LazyCollection`](https://laravel.com/docs/collections#lazy-collections), which FastExcel streams row by row — no wrapper needed:

```
// Export consumes only a few MB, even with 10M+ rows.
(new FastExcel(User::cursor()))->export('users.xlsx');
```

For any other source, hand `export()` a generator [using `yield`](https://www.php.net/manual/en/language.generators.syntax.php):

```
function rowsGenerator() {
    foreach (some_paginated_source() as $row) {
        yield $row;
    }
}

(new FastExcel(rowsGenerator()))->export('test.xlsx');
```

Exporting 1,000,000 rows (4 columns) under a 512 MB `memory_limit`:

How you exportPeak memoryResult`export()` from a materialized collection&gt; 512 MB**fails** once it exceeds `memory_limit``export()` from a cursor / generator (streaming)~4 MBalways completesStreaming does not change export *speed* (that is dominated by the underlying [OpenSpout](https://github.com/openspout/openspout) writer) — it is what keeps memory flat so very large files finish at all. `transpose()` cannot stream, as it must buffer the whole dataset to pivot rows and columns.

### Import large files (low memory)

[](#import-large-files-low-memory)

`import` returns a Collection containing every row, so memory grows with the size of the file. On a file larger than your PHP `memory_limit`, the default `import()` fails outright with `Allowed memory size of N bytes exhausted`. To import a large file without running out of memory, pass a callback and **return `null`** — each row is then processed but not accumulated, so memory stays flat:

```
// Memory stays flat regardless of the number of rows.
(new FastExcel)->import('file.xlsx', function ($line) {
    User::create([
        'name'  => $line['Name'],
        'email' => $line['Email'],
    ]);

    return null; // don't keep the row in memory
});
```

> If the callback returns a value (for example the created model), that value is collected and returned to you — handy for small files, but it keeps every row in memory. Return `null` when you only need the side effect (e.g. inserting rows).

Importing a 730,000-row file (8 columns), measured under a constrained `memory_limit`:

How you importPeak memoryResult`import($file)` (returns a Collection)~440 MB**fails** once it exceeds `memory_limit``import($file, fn ($row) => null)` (streaming)~4 MBalways completesReading speed is the same either way — it is dominated by the underlying [OpenSpout](https://github.com/openspout/openspout) parser, not by how the rows are returned. The difference above is memory, which is what lets very large files finish at all.

If you would rather keep working with the rows than process them inside a callback, `importLazy` returns a [`LazyCollection`](https://laravel.com/docs/collections#lazy-collections)that streams rows one at a time — you get the full Collection API while memory stays flat:

```
use Illuminate\Support\LazyCollection;

(new FastExcel)->importLazy('file.xlsx')
    ->chunk(1000)
    ->each(function (LazyCollection $chunk) {
        User::insert($chunk->all());
    });
```

`importLazy` accepts the same optional callback as `import`, and honors `sheet()`, `withoutHeaders()`, and header de-duplication. Transposing (`transpose()`) is not supported with lazy import.

### Add header and rows style

[](#add-header-and-rows-style)

Add header and rows style with `headerStyle` and `rowsStyle` methods.

```
use OpenSpout\Common\Entity\Style\Style;

$header_style = (new Style())->setFontBold();

$rows_style = (new Style())
    ->setFontSize(15)
    ->setShouldWrapText()
    ->setBackgroundColor("EDEDED");

return (new FastExcel($list))
    ->headerStyle($header_style)
    ->rowsStyle($rows_style)
    ->download('file.xlsx');
```

You can also style each header column individually with `setHeaderColumnStyles`(the header-row counterpart of `setColumnStyles`). Keys are the zero-based column positions:

```
use OpenSpout\Common\Entity\Style\Color;
use OpenSpout\Common\Entity\Style\Style;

return (new FastExcel($list))
    ->setHeaderColumnStyles([
        0 => (new Style())->setBackgroundColor(Color::YELLOW),
        1 => (new Style())->setFontColor(Color::BLUE),
    ])
    ->download('file.xlsx');
```

### Export values as strings or numbers

[](#export-values-as-strings-or-numbers)

By default numbers are written as numbers and strings as strings. Use `stringValues()` to force every value to a text cell — handy to keep leading zeros or long numeric IDs (e.g. phone numbers) intact:

```
// 0660123456 stays "0660123456" instead of becoming 660123456
(new FastExcel($users))->stringValues()->export('users.xlsx');
```

Need finer control? `setColumnFormat()` overrides the type per column and takes precedence over `stringValues()`:

```
(new FastExcel($users))
    ->stringValues()                                  // text by default
    ->setColumnFormat([
        'id'    => 'number',                          // keep as number
        'phone' => 'string',                          // keep as text
    ])
    ->export('users.xlsx');
```

Why?
----

[](#why)

FastExcel is intended at being Laravel-flavoured [Spout](https://github.com/box/spout): a simple, but elegant wrapper around [Spout](https://github.com/box/spout) with the goal of simplifying **imports and exports**. It could be considered as a faster (and memory friendly) alternative to [Laravel Excel](https://laravel-excel.com/), with less features. Use it only for simple tasks.

Benchmarks
----------

[](#benchmarks)

XLSX export of 10,000 rows × 20 columns of random data, average of 10 runs (PHP 8.4, July 2026). **Don't trust benchmarks.**

[![FastExcel vs Laravel Excel — memory and time benchmark](bench/benchmark.svg)](bench/benchmark.svg)

Peak memoryExecution timeLaravel Excel 3.1218 MB2.53 sFastExcel — collection42 MB0.90 s**FastExcel — generator****4 MB****0.93 s**FastExcel streams rows through [OpenSpout](https://github.com/openspout/openspout) instead of building the whole spreadsheet in memory. Feed it a generator (or `importLazy()` on the read side) and peak memory stays flat no matter how many rows you export — here about **55× less** than Laravel Excel. Reproduce with [`bench/readme-export-bench.php`](bench/readme-export-bench.php).

Still, remember that [Laravel Excel](https://laravel-excel.com/) **has many more features.**

###  Health Score

80

—

ExcellentBetter than 100% of packages

Maintenance96

Actively maintained with recent releases

Popularity77

Solid adoption and visibility

Community48

Growing community involvement

Maturity85

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 66.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~44 days

Recently: every ~7 days

Total

70

Last Release

20d ago

Major Versions

v0.12.0 → v1.0.02019-01-02

v1.7.0 → v2.0.02020-06-16

v2.5.0 → v3.0.02021-05-01

v3.2.0 → v4.0.02022-07-13

v4.1.0 → v5.0.02022-12-09

PHP version history (5 changes)v0.10.0PHP ^7.0

v2.2.0PHP ^7.1

v2.3.0PHP ^7.1|^8.0

v4.1.0PHP ^7.3 || ^8.0

v5.0.0PHP ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/849c3b70e82874c89e079738e4879e0eabb71d1a73f53e81b88c39a9b40f32ae?d=identicon)[rap2hpoutre](/maintainers/rap2hpoutre)

---

Top Contributors

[![rap2hpoutre](https://avatars.githubusercontent.com/u/1575946?v=4)](https://github.com/rap2hpoutre "rap2hpoutre (144 commits)")[![elminson](https://avatars.githubusercontent.com/u/2476286?v=4)](https://github.com/elminson "elminson (28 commits)")[![johanrosenson](https://avatars.githubusercontent.com/u/10432296?v=4)](https://github.com/johanrosenson "johanrosenson (5 commits)")[![crynobone](https://avatars.githubusercontent.com/u/172966?v=4)](https://github.com/crynobone "crynobone (3 commits)")[![dannyyol](https://avatars.githubusercontent.com/u/49995498?v=4)](https://github.com/dannyyol "dannyyol (3 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (3 commits)")[![henryavila](https://avatars.githubusercontent.com/u/8429941?v=4)](https://github.com/henryavila "henryavila (2 commits)")[![svenluijten](https://avatars.githubusercontent.com/u/11269635?v=4)](https://github.com/svenluijten "svenluijten (2 commits)")[![markdieselcore](https://avatars.githubusercontent.com/u/16547382?v=4)](https://github.com/markdieselcore "markdieselcore (2 commits)")[![Pochwar](https://avatars.githubusercontent.com/u/9018038?v=4)](https://github.com/Pochwar "Pochwar (2 commits)")[![klimov-paul](https://avatars.githubusercontent.com/u/1482054?v=4)](https://github.com/klimov-paul "klimov-paul (1 commits)")[![krenor](https://avatars.githubusercontent.com/u/13726968?v=4)](https://github.com/krenor "krenor (1 commits)")[![maherelgamil](https://avatars.githubusercontent.com/u/6294478?v=4)](https://github.com/maherelgamil "maherelgamil (1 commits)")[![mashkovtsevlx](https://avatars.githubusercontent.com/u/9170009?v=4)](https://github.com/mashkovtsevlx "mashkovtsevlx (1 commits)")[![matejjurancic](https://avatars.githubusercontent.com/u/4748399?v=4)](https://github.com/matejjurancic "matejjurancic (1 commits)")[![micalm](https://avatars.githubusercontent.com/u/9348336?v=4)](https://github.com/micalm "micalm (1 commits)")[![mokhosh](https://avatars.githubusercontent.com/u/6499685?v=4)](https://github.com/mokhosh "mokhosh (1 commits)")[![oriceon](https://avatars.githubusercontent.com/u/358823?v=4)](https://github.com/oriceon "oriceon (1 commits)")[![pushchris](https://avatars.githubusercontent.com/u/679974?v=4)](https://github.com/pushchris "pushchris (1 commits)")[![scrutinizer-auto-fixer](https://avatars.githubusercontent.com/u/6253494?v=4)](https://github.com/scrutinizer-auto-fixer "scrutinizer-auto-fixer (1 commits)")

---

Tags

csvexcelfasthacktoberfestlaravellaravel-packagememory-efficiencyphpxlsxlaravelexcelxlsxlsxcsv

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/rap2hpoutre-fast-excel/health.svg)

```
[![Health](https://phpackages.com/badges/rap2hpoutre-fast-excel/health.svg)](https://phpackages.com/packages/rap2hpoutre-fast-excel)
```

###  Alternatives

[maatwebsite/excel

Supercharged Excel exports and imports in Laravel

12.7k162.0M969](/packages/maatwebsite-excel)[avadim/fast-excel-laravel

Lightweight and very fast XLSX Excel Spreadsheet Export/Import for Laravel

4263.3k1](/packages/avadim-fast-excel-laravel)[emiliogrv/nova-batch-load

A Laravel Nova XLS &amp; CSV importer

1641.9k](/packages/emiliogrv-nova-batch-load)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
