1. 程式人生 > >laravel-excel maatwebsite/excel 新版中文文件

laravel-excel maatwebsite/excel 新版中文文件

laravel 專案從 5.2 升級到了 5.7,Excel 的匯入匯出,使用的 maatwebsite/excel laravel-excel 依賴包,也從 2.* 升級到了 3.*,發現不能用了,開啟文件一看,這尼瑪改動也太大了吧,完全不能使用的節奏啊!

先分享幾個連結:
	github 地址:
		https://github.com/Maatwebsite/Laravel-Excel

	官網地址:
		https://laravel-excel.maatwebsite.nl

	看文件的升級指南,可以發現官方推薦了個連結,有人從 2.x 升級到 3.x,專案裡進行的程式碼修改
		https://github.com/Maatwebsite/Laravel-Excel/issues/1799
PS:
	想搜下新版的中文文件,開啟 google 搜尋,輸入 'maatwebsite/excel 中文文件',發現第 3 條居然是我之前寫的部落格,開啟一看,嚇我一跳,我尼瑪壓根沒有一點印象,之前居然總結過舊版文件,而且寫了 700 多行,有點吃驚,我以前居然這麼有耐心~

好了,閒話少數,開始新版文件學習之旅~
	依賴:
		PHP: ^7.0
		Laravel: ^5.5
		PhpSpreadsheet: ^1.4
		php_zip
		php_xml
		php_gd2

	安裝:
		composer require maatwebsite/excel

	配置:
		Maatwebsite\Excel\ExcelServiceProvider 預設是自動發現並註冊,我們也可以手動新增:
			config/app.php
				'providers' => [
					/*
					 * Package Service Providers...
					 */
					Maatwebsite\Excel\ExcelServiceProvider::class,
				]

		Excel 門面(Facade)也是自動發現,也可以手動新增:
			config/app.php
				'aliases' => [
					...
					'Excel' => Maatwebsite\Excel\Facades\Excel::class,
				]

		釋出配置檔案:
			php artisan vendor:publish
			會建立 config/excel.php

	匯出:
		1.5分鐘快速入門:
			在 App/Exports 下建立匯出類
				php artisan make:export UsersExport --model=User

			UserExport.php 內容:
				<?php

					namespace App\Exports;

					use App\User;
					use Maatwebsite\Excel\Concerns\FromCollection;

					class UsersExport implements FromCollection
					{
					    public function collection()
					    {
					        return User::all();
					    }
					}

			控制器裡呼叫匯出:
				use App\Exports\UsersExport;
				use Maatwebsite\Excel\Facades\Excel;
				use App\Http\Controllers\Controller;

				class UsersController extends Controller 
				{
				    public function export() 
				    {
				        return Excel::download(new UsersExport, 'users.xlsx');
				    }
				}

			這樣就匯出了個 'users.xlsx' 檔案

		2.匯出集合
			匯出的最簡單方式是,建立一個自定義的匯出類。就是使用之前的命令,在 App/Exports 下建立一個匯出類
				php artisan make:export UsersExport --model=User

			1>常用方法
				控制器裡下載:
					public function export() 
					{
					    return Excel::download(new InvoicesExport, 'invoices.xlsx');
					}

				控制器裡儲存到硬碟:
					public function storeExcel() 
					{
					    return Excel::store(new InvoicesExport, 'invoices.xlsx', 's3');
					}

			2>依賴注入:
				另一種寫法,看文件

			3>集合巨集:
				Laravel-Excel 為 Laravel 的匯出集合類,提供了一些巨集,更方便的下載和儲存集合。

				下載:
					(new Collection([
						[1, 'dongxuemin', 30], 
						[2, 'yangyaping', 30])
					)->downloadExcel($filePath, $writerType = null, $headings = false);

				儲存:
					(new Collection([
						[1, 'dongxuemin', 30], 
						[2, 'yangyaping', 30])
					)->storeExcel($filePath, $disk = null, $writerType = null, $headings = false);

				總結:
					我們可以自己利用 new Collection 來構造集合,進行下載和儲存

		3.在硬碟上儲存匯出資料:
			匯出可以很容易地被儲存到 Laravel 所支援的任意檔案系統。

			1>不傳遞引數,預設檔案系統
				Excel::store(new InvoicesExport(2018), 'invoices.xlsx');

			2>儲存到 's3' 檔案系統
				Excel::store(new InvoicesExport(2018), 'invoices.xlsx', 's3');

			3>儲存到 's3' 檔案系統,並指定 'writer' 型別
				Excel::store(new InvoicesExport(2018), 'invoices.xlsx', 's3', Excel::XLSX);

		4.匯出格式:
			預設情況下,匯出格式由匯出檔案的字尾決定,例如:'user.xlsx',匯出格式就是:\Maatwebsite\Excel\Excel::XLSX。我們也可以傳遞第二個引數,顯式地指定匯出格式。
				(new InvoicesExport)->download('invoices.xlsx', \Maatwebsite\Excel\Excel::XLSX);

			支援的格式有:
				XLSX
				CSV
				TSV
				ODS
				XLS
				SLK
				XML
				GNUMERIC
				HTML
				MPDF
				DOMPDF
				TCPDF

		5.可匯出的
			之前的方法中,我們使用 Excel::download 門面(Facade) 來匯出。
			例如:在控制器中使用 Excel::download(new InvoicesExport(2018));

			Laravel Excel 也提供了一個 'Maatwebsite\Excel\Concerns\Exportable' trait,使得我們建立的匯出類,本身具有可匯出的方法。

			示例:
				use Maatwebsite\Excel\Concerns\Exportable;

				class InvoicesExport implements FromCollection
				{
				    use Exportable;

				    public function collection()
				    {
				        return Invoice::all();
				    }
				}

			這樣,InvoicesExport 類本身就具有可匯出方法,不用再使用 Excel 門面(Facade)

			下載:
				return (new InvoicesExport)->download('invoices.xlsx');

			儲存:
				return (new InvoicesExport)->store('invoices.xlsx', 's3');

			可響應:
				可以使用 'Responsable' 介面,進一步簡化匯出操作。

				use Illuminate\Contracts\Support\Responsable;
				class InvoicesExport implements FromCollection, Responsable
				{

					// 要求必須指定 'fileName' 屬性(匯出的檔名)
					private $fileName = 'invoices.xlsx';	
				}

				下載:
					return new InvoicesExport();

		6.從查詢匯出
			在之前的例子中,我們在匯出類中進行查詢。對於小型匯出,這個是一個非常好的解決方案,但是對於大型匯出,會有很大的效能開銷。

			通過使用 'FromQuery',我們可以為匯出準備一個查詢。在底層,'FromQuery' 查詢使用了 chunks 查詢,以減少效能開銷。

			普通查詢:

				示例:
					use Maatwebsite\Excel\Concerns\FromQuery;		// 引入 'FromQuery'

					class InvoicesExport implements FromQuery		// 實現 'FromQuery'
					{
					    use Exportable;

					    public function query()
					    {
					        return Invoice::query();				// 確保不要使用 'get()' 方法
					    }
					}

				下載:
					return (new InvoicesExport)->download('invoices.xlsx');

			自定義查詢

				/*
					這個應該是我們最經常使用的方法!!!
					我們一般都是根據使用者的各種篩選條件,然後進行 query 查詢,然後得到最終的結果列表,再進行匯出。
					但因為新版,匯出的資料結果,都是通過外部的匯出類來實現了,我們必須將 query 引數,傳遞到匯出類中,來獲取結果集。
				 */

				普通示例:
					use Maatwebsite\Excel\Concerns\FromQuery;		// 引入 'FromQuery'

					class InvoicesExport implements FromQuery		// 實現 'FromQuery'
					{
					    use Exportable;

					    public function __construct(int $year)		// 匯入外部查詢引數
					    {
					        $this->year = $year;
					    }

					    public function query()
					    {
					        return Invoice::query()->whereYear('created_at', $this->year);			// 使用 where 查詢
					    }
					}

					下載:
						// 傳遞查詢引數
						return (new InvoicesExport(2018))->download('invoices.xlsx');

				設定器示例(另一種寫法):
					use Maatwebsite\Excel\Concerns\FromQuery;		// 引入 'FromQuery'

					class InvoicesExport implements FromQuery		// 實現 'FromQuery'
					{
					    use Exportable;

					    public function forYear(int $year)			// 定義 '設定器'
					    {
					        $this->year = $year;
					        
					        return $this;
					    }

					    public function query()
					    {
					        return Invoice::query()->whereYear('created_at', $this->year);			// 使用 where 查詢
					    }
					}

					下載:
						// 呼叫 '設定器'
						return (new InvoicesExport)->forYear(2018)->download('invoices.xlsx');

		7.從模板中匯出
			定義匯出類,同時定義一個匯出模板,Laravel Excel 會將定義的 HTML table 轉換為一個 Excel 電子表單

			示例:
				use Illuminate\Contracts\View\View;
				use Maatwebsite\Excel\Concerns\FromView;

				class InvoicesExport implements FromView
				{
				    public function view(): View
				    {
				        return view('exports.invoices', [
				            'invoices' => Invoice::all()
				        ]);
				    }
				}

			Blade 模板,定義一個標準的 <table> 即可,<thead> - 表頭 & <tbody> - 表內容
				<table>
				    <thead>
				    <tr>
				        <th>Name</th>
				        <th>Email</th>
				    </tr>
				    </thead>
				    <tbody>
				    @foreach($users as $user)
				        <tr>
				            <td>{{ $user->name }}</td>
				            <td>{{ $user->email }}</td>
				        </tr>
				    @endforeach
				    </tbody>
				</table>

		8.佇列
			如果處理大量的資料匯出,推薦使用佇列來進行匯出。

			佇列匯出,底層實現是:使用 chunk 查詢,多個 job 任務連結在一起(應該是按順序連結)。這些 job 任務以插入佇列的先後順序正確執行,只有當前面的任務執行成功,後面的才會執行。

			普通示例:
				匯出類定義一致

				下載,直接呼叫 'queue()' 方法
					(new InvoicesExport)->queue('invoices.xlsx');
					return back()->withSuccess('Export started!');

			顯示定義匯出到佇列
				use Maatwebsite\Excel\Concerns\FromQuery;
				use Illuminate\Contracts\Queue\ShouldQueue;			// 引入 'ShouldQueue'

				class InvoicesExport implements FromQuery, ShouldQueue		// 實現 'ShouldQueue'
				{
				    use Exportable;

				    public function query()
				    {
				        return Invoice::query();
				    }
				}

				下載,使用 'store()' 方法
					(new InvoicesExport)->store('invoices.xlsx');

			追加佇列任務
				queue() 方法返回 Laravel 的 'PendingDispatch' 例項。意味著,我們可以在佇列尾部新增額外的 job 任務,新新增的匯出任務,只有在之前的匯出都正確後,才會執行。

				示例:
					use Illuminate\Bus\Queueable;					// 引入 'Queueable'
					use Illuminate\Contracts\Queue\ShouldQueue;
					use Illuminate\Queue\SerializesModels;			// 引入 'SerializesModels'

					class NotifyUserOfCompletedExport implements ShouldQueue
					{
					    use Queueable, SerializesModels;			// 使用 'Queueable' & 'SerializesModels'
					    
					    public $user;
					    
					    public function __construct(User $user)		// 傳遞引數
					    {
					        $this->user = $user;
					    }

					    public function handle()					// 呼叫了 'handle()' 方法
					    {
					        $this->user->notify(new ExportReady());
					    }
					}

				追加:
					(new InvoicesExport)->queue('invoices.xlsx')->chain([
					    new NotifyUserOfCompletedExport(request()->user()),		// 傳遞引數
					]);

			自定義佇列:
				由於返回了 'PendingDispatch',我們也可以更改使用的佇列。(有時間可看下 PendingDispatch 原始碼)

				(new InvoicesExport)->queue('invoices.xlsx')->allOnQueue('exports');

		9.多個表單
			多表單的匯出,需要使用 'WithMultipleSheets'。然後在匯出類中,實現 'sheets()' 方法,sheets() 方法,返回一個由 '單個表單物件' 組成的陣列。

			多表單的匯出,需要2個類:
				1>匯出類
				2>單個表單類

			示例:
				1>匯出類
					use Maatwebsite\Excel\Concerns\WithMultipleSheets;

					class InvoicesExport implements WithMultipleSheets
					{

						// 實現 sheets() 方法,返回一個由 '單個表單物件' 組成的陣列。
					    public function sheets(): array
					    {
					        $sheets = [];

					        for ($month = 1; $month <= 12; $month++) {
					            $sheets[] = new InvoicesPerMonthSheet($this->year, $month);
					        }

					        return $sheets;
					    }
					}

				2>單個表單類,可以實現 'FromQuery','FromCollection',...
					use Maatwebsite\Excel\Concerns\FromQuery;		// 引入 'FromQuery'
					use Maatwebsite\Excel\Concerns\WithTitle;		// 引入 'WithTitle'(可修改 excel 表單名)

					class InvoicesPerMonthSheet implements FromQuery, WithTitle
					{

						// 查詢
					    public function query()
					    {
					        return Invoice
					            ::query()
					            ->whereYear('created_at', $this->year)
					            ->whereMonth('created_at', $this->month);
					    }

					    // Excel 電子表單名
					    public function title(): string
					    {
					        return 'Month ' . $this->month;
					    }
					}

		10.對映資料
			對映行
				新增 'WithMapping',我們可以定義一個 'map()' 方法,將查詢到的每條資料,經過 map() 方法處理,返回我們需要的 '一整行'。

				示例:
					use Maatwebsite\Excel\Concerns\WithMapping;		// 引入 'WithMapping'

					class InvoicesExport implements FromQuery, WithMapping		// 實現 'WithMapping'
					    
					    // 定義 'map()' 方法,引數是 '查詢出來的每行資料物件'
					    public function map($invoice): array
					    {
					        return [
					            $invoice->invoice_number,
					            Date::dateTimeToExcel($invoice->created_at),
					        ];
					    }
					}

			新增標題行
				新增 'WithHeadings',定義 'headings()' 方法,來新增標題行

				示例:
					use Maatwebsite\Excel\Concerns\WithHeadings;		// 引入 'WithHeadings'

					class InvoicesExport implements FromQuery, WithHeadings		// 實現 'WithHeadings'
					    
					    // 定義 'headings()' 方法
					    public function headings(): array
					    {
					        return [
					            '#',
					            'Date',
					        ];
					    }
					}

		11.格式化列
			使用 'WithColumnFormatting',定義 'columnFormats()' 方法,我們可以輕鬆格式化整列資料。	

			如果想要更多自定義內容,建議使用 AfterSheet 事件直接與底層 Worksheet 類進行互動。

			示例:
				use PhpOffice\PhpSpreadsheet\Shared\Date;			// 日期處理
				use PhpOffice\PhpSpreadsheet\Style\NumberFormat;	// 數字格式化
				use Maatwebsite\Excel\Concerns\WithColumnFormatting;		// 引入 '列格式化'
				use Maatwebsite\Excel\Concerns\WithMapping;

				class InvoicesExport implements WithColumnFormatting, WithMapping
				{
				    public function map($invoice): array
				    {
				        return [
				            $invoice->invoice_number,
				            Date::dateTimeToExcel($invoice->created_at),
				            $invoice->total
				        ];
				    }
				    
				    /**
				     * @return array
				     */
				    public function columnFormats(): array
				    {
				        return [
				            'B' => NumberFormat::FORMAT_DATE_DDMMYYYY,
				            'C' => NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE,
				        ];
				    }
				}

			日期處理:
				推薦在 map() 方法中使用 '\PhpOffice\PhpSpreadsheet\Shared\Date::dateTimeToExcel()'

			自動調整尺寸:
				引入 'ShouldAutoSize',讓 Laravel Excel 自動調整單元格寬度

				use Maatwebsite\Excel\Concerns\ShouldAutoSize;
				Class InvoicesExport implements ShouldAutoSize
				{

				}

		12.提供的所有可用的 'Export concerns'
			介面:
				Maatwebsite\Excel\Concerns\FromArray - 使用 array 來實現匯出
				Maatwebsite\Excel\Concerns\FromCollection - 使用 Laravel collection 來實現匯出
				Maatwebsite\Excel\Concerns\FromIterator - 使用 iterator(迭代器)來實現匯出
				Maatwebsite\Excel\Concerns\FromQuery - 使用 Eloquent query 來實現匯出
				Maatwebsite\Excel\Concerns\FromView - 使用 (Blade) 模板來實現匯出
				Maatwebsite\Excel\Concerns\WithTitle - 設定工作簿或工作表標題
				Maatwebsite\Excel\Concerns\WithHeadings - 新增表頭
				Maatwebsite\Excel\Concerns\WithMapping - 在寫入檔案前,格式化行
				Maatwebsite\Excel\Concerns\WithColumnFormatting - 格式化列
				Maatwebsite\Excel\Concerns\WithMultipleSheets - 開啟多表單支援
				Maatwebsite\Excel\Concerns\ShouldAutoSize - 在工作表中,自動調整列寬
				Maatwebsite\Excel\Concerns\WithStrictNullComparison - 在測試單元格的 null 時,使用嚴格比較
				Maatwebsite\Excel\Concerns\WithEvents - 註冊事件,掛載到 'PhpSpreadsheet' 處理過程中
				Maatwebsite\Excel\Concerns\WithCustomQuerySize - 允許 'Exportable' 實現 'FromQuery',來提供它們自己的自定義查詢大小。
				Maatwebsite\Excel\Concerns\WithCustomCsvSettings - 允許對指定的匯出,執行自定義的 CSV 設定。
				Maatwebsite\Excel\Concerns\WithCharts - 允許執行一個或多個 PhpSpreadsheet Chart 例項
				Maatwebsite\Excel\Concerns\WithDrawings - 允許執行一個或多個 PhpSpreadsheet Drawing 例項
				Maatwebsite\Excel\Concerns\WithCustomStartCell - 允許指定一個自定義起始單元格。注意:僅支援 'FromCollection' 匯出

			Traits:
				Maatwebsite\Excel\Concerns\Exportable - 給匯出類自身新增 'download()' 和 'store()' 方法
				Maatwebsite\Excel\Concerns\RegistersEventListeners

		13.擴充套件
			有點複雜,不總結了,看文件


	匯入:
		匯出寫的有點累了,有時間再完善...