Laravel Excel: How to append rows to an existing Excel file

Seth ChenSeth Chen
2 min read

Hey guys,

Well damn, it has been a while since my last post lol, lazy & busy. But here I am, back to write useful tips for y’all 🥹

Let us do some exporting tasks for today, using Laravel Excel to export XLSX (yeah CSV is so 2010 lol). But, append more rows to an existing file.

The approach

From your export class (e.g.: UserExport), implements the WithEvents

Once you added the registerEvents method, add this

    public function registerEvents(): array
    {
        return [
            BeforeWriting::class => function (BeforeWriting $event) {
                if (!Storage::exists($this->filePath)) {
                    return;
                }

                file_put_contents(
                    $tempFile = tempnam('/tmp', 'export') . '.xlsx',
                    Storage::get($this->filePath)
                );

                $templateFile = new LocalTemporaryFile($tempFile);

                $event->writer->reopen($templateFile, Excel::XLSX);
                $event->writer->getSheetByIndex(0)
                    ->export($event->getConcernable());

                return $event->writer->getSheetByIndex(0);
            },
        ];
    }

It will retrieve the file from your desired storage (local, public, s3, etc), store to tmp folder (which is available for both server & serverless environment), and tell Laravel Excel to use that file to write more rows.

Simple right?

And yeah, I know, it’s a shame that reading an existing file is not available in the package.

After this, what do we get?

Daisy-chaining jobs to export tons of rows

Yep, each job can write around 500 ~ 1000 rows, then store the file, and dispatch another job to continue until it writes all rows.

Reduce memory-leak or timeout issues, since jobs only handle a small amount of data.

Interact with S3 with ease

Thanks to Storage from Laravel, this can be done super easy.

With the code above, I’ve read the file, and to write, simply:

Excel::store(
    new UserExport(collect($users), $this->filePath),
    $this->filePath
);

Works for both Server & Serverless

Yep, tested on both server & serverless (Lambda), lovely!

Finally

Thanks for reading and have fun!

0
Subscribe to my newsletter

Read articles from Seth Chen directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Seth Chen
Seth Chen

develops awesome software, contributes to OSS, writes tech tips, and loves Vietnamese milk coffee!