Laravel6 配合 Maatwebsite\Excel 實現 Excel 匯出

sai0556發表於2020-09-08

相比匯入,專案中匯出場景更多,估摸著現在有十多個匯出了,之前寫了匯入,這會才把匯出補上。

安裝之前說過,這裡說一下配置,雖然已有預設配置,但還是有修改配置的場景,所以建議生成配置檔案。

配置

//生成config/excel.php
php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider"

配置只提一個,其他註釋蠻細的,

'csv' => [
    'delimiter'              => ',',
    'enclosure'              => '"',
    'line_ending'            => PHP_EOL,
    // 匯出csv中文亂碼,把use_bom設為true即可
    'use_bom'                => true,
    'include_separator_line' => false,
    'excel_compatibility'    => false,
],

接下來,來完成一個匯出的demo說明下常用的一些點。

DEMO

php artisan make:export MultiExport

生成檔案如下:

<?php

namespace App\Exports;

use Maatwebsite\Excel\Concerns\FromCollection;

class MultiExport implements FromCollection
{
    /**
    * @return \Illuminate\Support\Collection
    */
    public function collection()
    {
        //
    }
}
  • 自定義sheet,增加 WithTitle
  • 自定義列名,增加WithHeadings
  • 不想使用Collection,替換FromCollection使用FromArray
  • 多個sheet,替換FromCollection使用WithMultipleSheets

經過改造:

<?php
/**
 * 多重匯出
 */
namespace App\Exports;

use App\Exports\MultiExportA;
use App\Exports\MultiExportB;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;

class MultiExport implements WithMultipleSheets
{
    private $date;

    public function __construct($date)
    {
        $this->date = $date;
    }


    public function sheets(): array
    {
        $sheets = [];

        $sheets[] = new MultiExportA($this->date);
        $sheets[] = new MultiExportB($this->date);

        return $sheets;
    }
}

---
// MultiExportA,MultiExportB類比即可
<?php

namespace App\Exports;

use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithTitle;
use App\Models\ExportA;

class MultiExportA implements FromArray, WithTitle, WithHeadings
{
    private $date;

    public function __construct($date, $cityId)
    {
        $this->date = $date;
    }

    public function headings(): array
    {
        return [
            'ID',
            '名稱',
            '價格',
            '手機'
        ];
    }


    /**
    * @return array
    */
    public function array() : array
    {
        $data = ExportA::where('date', $this->date)
            ->get()
            ->toArray();

        $ret = [];
        foreach ($data as $val) {
            // 一段神奇的程式碼計算出了價格
            $price = ...;
            $ret[] = [
                'id' => $val['id']."\t",
                'name' => $val['name'],
                'price' => $price,
                // 轉換為文字,編碼excel使用了科學計數法
                'mobile' => $val['mobile']."\t",
            ];
        }
        return $ret;
    }

    /**
     * @return string
     */
    public function title(): string
    {
        return '表格A';
    }
}

使用

// 儲存
$obj = new MultiExport($date);
Excel::store($obj, 'MultiExport'.$date.'.xlsx');

// 下載csv
Excel::download($obj, 'MultiExport'.$date.'.csv', \Maatwebsite\Excel\Excel::CSV, ['Content-Type' => 'text/csv']);

問題思考

當資料量過大的時候,匯出時很可能會記憶體溢位了。建議:

  • 使用其他高效能的元件,或者使用原生程式碼流式輸出到瀏覽器,也可以直接使用其他語言(比如go)編寫
  • 檔案過大,Excel開啟大資料量檔案也很雞肋,容易卡死甚至崩潰,嘗試分檔案匯出,比如1w一個檔案
  • 部分匯出過程可能有計算,可以提前計算好,匯出時直接讀表,使用LazyCollection, 使用 Lazy Collections 來提高 Laravel Excel 讀取的效能(輕鬆支援百萬資料)
本作品採用《CC 協議》,轉載必須註明作者和本文連結
收藏前不妨點個贊試試!!! 分享開發知識,歡迎交流。qq交流群:965666112,公眾號:愛好歷史的程式設計師。 點選直達個人部落格

相關文章