Laravel Excelをマスターしよう

Laravel8.x, Laravel6.x, Laravel 5.8, 5.7で動作確認を行っています。
Webアプリケーションを構築するとサードパーティからのデータを取り込んだり、他のアプリケーションやEXCELでデータ加工を行いたい場合にCSVファイルのExport/Import機能が必ず必要となります。CSVだけでなくEXCELでもExport/Importを利用することができればユーザに喜ばれることは間違いないです。Webアプリケーションに必須な機能なのでぜひLaravel Excelの使い方をマスターしてください。
本文書では、Laravel上でEXCELファイルをExport/ImportするためのパッケージLaravel Excelの使用方法について説明を行なっています。本文書を読み終えるとテーブルに保存されているデータをEXCELファイルでダウンロード、または保存することができます。さらにEXCELファイルに保存しているデータを一括でテーブルに保存することができます。

目次
動作確認環境
動作確認を行う環境はLaravelがインストールが完了し、データベースにusersテーブルが存在する環境で行っています。
Laravel8での変更について
Laravel8ではモデルファイルの保存先がappからapp¥Modelsに変更になっています。またweb.phpへのルーティングを設定する際にuseを使ってコントローラーをimportします。Laravel8でのコードも併記して記述しています。
Laravel Excelのインストール
Laravel Excelを使用するためにComposerを利用してmaatwebsite/excelのインストールを行います。
$ composer require maatwebsite/excel
Composerがわからない人は下記の文書がおすすめです。
インストールすると下記のパッケージがインストールされます。
laravel $ composer require maatwebsite/excel
Using version ^3.1 for maatwebsite/excel
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 4 installs, 0 updates, 0 removals
- Installing markbaker/matrix (1.1.4): Downloading (100%)
- Installing markbaker/complex (1.4.7): Downloading (100%)
- Installing phpoffice/phpspreadsheet (1.8.2): Downloading (100%)
- Installing maatwebsite/excel (3.1.15): Downloading (100%)

Exportファイルの作成
Laravel Exportを使用してExcelファイルを作成する場合はLaravel ExportのExportクラスを利用します。ExportするExcelファイルへの各種設定(列名の設定やシートの名前)はこのファイルを利用して行うことができます。Laravel Excelでは非常に重要な役割を持っています。
Export用のクラスはphp artisan make:exportコマンドで作成することができます。

usersテーブルに入ったデータをExportしてExcelファイルの作成を行うためmodelオプションでUserを指定して、ファイル名はUsersExportとします。
$ php artisan make:export UsersExport --model=User
Export created successfully.
appフォルダの下にExport/UsersExport.phpが作成されます。作成したUsersExport.phpにはcollectionメソッドが記述されています。
<?php
namespace App\Exports;
use App\User;
use App\Models\User; //Laravel8の場合
use Maatwebsite\Excel\Concerns\FromCollection;
class UsersExport implements FromCollection
{
/**
* @return \Illuminate\Support\Collection
*/
public function collection()
{
return User::all();
}
}
テーブルからのデータ取得部分をUserExport.phpとして別ファイルにわけることで、取得したいデータが変わった場合はUserExport.phpのcollectionメソッドの中身を変えるだけで対応することができます。

usersテーブルに入っているデータをExportしたいので、必ずusersテーブルへのデータ挿入を完了させておいてください。
動作確認のためにusersテーブルへのテストデータの挿入する際はSeeding機能を使うことをおすすめします。
Laravel8の場合にテストデータを挿入したい場合は、database¥seeders¥DatabaseSeeder.phpファイルを開いて、runメソッドに入っているコメントを削除します。
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run()
{
\App\Models\User::factory(10)->create(); //この行のコメントを外す
}
}
コメントを外し、php artisan db:seedコマンドを実行するだけでusersテーブルに10件のダミーデータが保存されます。
% php artisan db:seed
Database seeding completed successfully.
usersテーブルにデータが挿入されたかどうかはデータベースの管理ツールを使っても行うことができますが、php artisan tinkerを使って確認もできます。こここでは、usersテーブルにデータが挿入されているか確認するためにphp artisan tinkerを実行します。
$ php artisan tinker
Psy Shell v0.9.9 (PHP 7.1.23 — cli) by Justin Hileman
>>> $users = App\User::all();
=> Illuminate\Database\Eloquent\Collection {#3003
all: [
App\User {#3004
id: "1",
name: "Vilma Bednar",
email: "ioreilly@example.com",
email_verified_at: "2019-07-30 01:29:27",
created_at: "2019-07-30 01:29:27",
updated_at: "2019-07-30 01:29:27",
},
Laravel8の場合は$users = App\Models\User::all();で実行してください。
usersテーブルデータのExport
Excelファイルのダウンロード
Exportを実行するコントローラーの作成を行なってください。ここでは、UsersControllerを作成します。
$ php artisan make:controller UsersController
Controller created successfully.
web.phpファイルに作成したUsersControllerコントローラーのルーティングを追加します。
Route::get('/', function () {
return view('welcome');
});
Route::get('users','UsersController@export');
Laravel8の場合はweb.phpは下記のように記述してください。
use App\Http\Controllers\UsersController;
Route::get('/', function () {
return view('welcome');
});
Route::get('users',[UsersController::class,'export']);
UsersControllerコントローラーにexportメソッドを記述します。
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\UsersExport;
class UsersController extends Controller
{
public function export(){
return Excel::download(new UsersExport, 'users.xlsx');
}
}
ここまでのExport設定が完了したらブラウザを使用して/usersにアクセスします。アクセスするとusers.xlsxファイルがダウンロードフォルダに保存されます。
users.xlsxファイルを開くとUsersテーブルに保存されているすべての行が保存されています。

もしusersテーブルのすべてのファイルではなく一部だけのデータのみダウンロードしたい場合は、UserExportファイルを更新することで対応することができます。下記ではidを1を持つユーザの情報のみダウンロードすることができます。
namespace App\Exports;
use App\Models\User;
use Maatwebsite\Excel\Concerns\FromCollection;
class UsersExport implements FromCollection
{
public function collection()
{
return User::where('id',1)->get();
}
}
EXCELファイルのヘッダー設定
先ほどの設定でダウンロードしたEXCELファイルには列名が表示されていませんでした。UserExport.phpファイルに下記の設定を行い列名を含むヘッダーを表示させます。headingsメソッドだけではなく、WithHeadingsインターフェイスを忘れずに追加してください。
use App\User;
use App\Models\User; //Laravel8の場合
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
class UsersExport implements FromCollection,WithHeadings
{
/**
* @return \Illuminate\Support\Collection
*/
public function collection()
{
return User::all();
}
public function headings():array
{
return [
'#',
'name',
'email',
'email_verified_at',
'created_at',
'updated_at'
];
}
}
ダウンロードしたファイルを開くと設定した列名が表示されます。


シートに名前をつける
デフォルトではExcelのシートの名前は”Worksheet”になっていますが、シート名を任意の名前に変更することができます。
シート名を変更するためには、UsersExport.phpファイルにWithTitleインターフェイスを追加します。WithTitleを追加した後にtitleメソッドを追加し、シート名は指定すればシート名を指定した文字列に変更することができます。下記ではシート名はtestで作成されます。
namespace App\Exports;
use App\User;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithTitle;
class UsersExport implements FromCollection, WithTitle
{
public function collection()
{
return User::all();
}
public function title(): string{
return 'test';
}
}
ダウンロードする列を指定
UsersExport.phpファイルのcollectionメソッドではUser::all()を指定していたためすべての列情報が表示されました。
public function collection()
{
return User::select('id','name','email')->get();
}
usersテーブルの中のidとnameとemailのみを取得することができます。collectionメソッドの内容を書き換えるだけで取得できるデータを変更することができるため、他のプログラムへの影響を最小限に留めることができます。
EXCEL以外のフォーマット保存
Laravel Excelという名前ですが、csvなどExcel以外のフォーマットにも対応しています。対応しているフォーマットはMaatwebsite\Excel\Excel.phpに記述されています。
class Excel implements Exporter, Importer
{
use RegistersCustomConcerns;
const XLSX = 'Xlsx';
const CSV = 'Csv';
const TSV = 'Csv';
const ODS = 'Ods';
const XLS = 'Xls';
const SLK = 'Slk';
const XML = 'Xml';
const GNUMERIC = 'Gnumeric';
const HTML = 'Html';
const MPDF = 'Mpdf';
const DOMPDF = 'Dompdf';
const TCPDF = 'Tcpdf';
下記のようにExcel::CSVを指定してダウンロードを行うとカンマ区切りのcsvファイルとして作成することができます。
public function export(){
return Excel::download(new UsersExport, 'users.csv', \Maatwebsite\Excel\Excel::CSV);
}
ダウンロードするフォーマットを指定しましたが、指定するファイル名の拡張子を変更するだけで自動でダウンロードするフォーマットを変更してくれます。
public function export(){
return Excel::download(new UsersExport, 'users.csv');
}
htmlファイルとして保存することができ、テーブル要素の中にデータを保存します。ファイル内でCSSが適用されているため、あまりきれいには表示されませんが、CSSを変更することで表示は簡単に変更することができます。

Exportableトレイト
ここまでの処理はExcel::downloadを使っていましたがExportableトレイトを使うと実行するコードを下記のように変更することができます。
public function export(){
return (new UsersExport)->download('test.xlsx');
}
ExportableトレイトはUsersExport.phpファイルで下記のように記述します。
namespace App\Exports;
use App\User;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\Exportable;
class UsersExport implements FromCollection
{
use Exportable;
public function collection()
{
return User::all();
}
}
複数シートのExcel作成
Laravel Excelを利用すると複数シートのExcelファイルの作成も簡単に行うことができます。
複数のシートを作成するためには、WithMultipleSheetsインターフェイスとsheetsメソッドが必要になります。1シートの場合はUsersExport.phpの中でcollectionメソッドを利用してデータを取得していましたが、複数シートの場合は、データを取得する別のクラスをsheetsメソッドの中で呼び出します。
forを使って1から10までの数字をUsersSheetクラスの中に挿入しています。
namespace App\Exports;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
class UsersExport implements WithMultipleSheets
{
public function sheets(): array{
$sheets = [];
for($i = 1; $i <= 10; $i++){
$sheets[] = new UsersSheet($i);
}
return $sheets;
}
}
UsersSheetクラスはUsersExportを複製して下記のように作成します。今回はインスタンス化の際に$idを受け取り、その値を元に検索を行っています。
namespace App\Exports;
use App\User;
use Maatwebsite\Excel\Concerns\FromCollection;
class UsersSheet implements FromCollection
{
protected $id;
public function __construct($id){
$this->id = $id;
}
public function collection()
{
return User::where('id',$this->id)->get();
}
}
UsersControllerはこれまで通り、UsersExportを指定しています。
public function export(){
return Excel::download(new UsersExport, 'test.xlsx');
}
ダウンロードを行うとtest.xlsxの中には10シートが作成され、それぞれのシートに1ユーザのみの行が挿入されています。

ここでは動作確認のために実行したこともあり、1シートに1ユーザの情報を取り出してExcelファイルを作成しました。複数のモデルのデータを別シートで取得したい場合は、UsersSheet.php以外にPostsSheetやInvoicesSheetを追加することで実現可能です。
サーバ上への保存する
テーブルから取り出したデータを保存したEXCELファイルをサーバ上のフォルダに保存する方法を確認します。ダウンロードする際は、downloadメソッドを利用しましたが、ディスクに保存する場合は、storeメソッドを利用します。保存される場所は、Laravelインストールディレクトリのstorage/appの下に保存されます。
Excel::store(new UsersExport, 'users.xlsx');
保存先は保存時の名前にパスを追加することでstorage/app以外に保存することができます。storage/appディレクトリの下にあるpublicに保存する場合は、下記のように変更することで行うことができます。
Excel::store(new UsersExport, 'public/users.xlsx');
Importファイルの作成
ここまではテーブルに保存されているデータをEXCELファイルへ保存するExportについて説明をしてきましたが、Laravel ExcelではExcelファイルに入ったデータをテーブルにimportすることもできます。サードパーティで作成されたデータをLaravelアプリケーションにimportしたい場合に重宝する昨日です。
本文書ではusersテーブルにデータをImportするためUserモデル用のImportファイルの作成を行います。
$php artisan make:import UsersImport --model=User
Import created successfully.
appフォルダの下にImport/UsersImport.phpが作成されます。作成したUsersImport.phpには、アップロードするEXCELファイルの列がインポートするテーブルのどの列に対応するのかを記述していきます。
namespace App\Imports;
use App\User;
use App\Models\User;
use Maatwebsite\Excel\Concerns\ToModel;
class UsersImport implements ToModel
{
/**
* @param array $row
*
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new User([
//
]);
}
}
インポートしたいデータが保存されたEXCELファイルを確認します。A列には名前、B列にはEmail、C列にはパスワードが入っています。

この列情報を元にUsersImport.phpを更新します。
usersテーブルnameには0列、emailには1列、passwordは暗号化を行うので、Hashを使って列2を暗号化しています。

public function model(array $row)
{
return new User([
'name' => $row[0],
'email' => $row[1],
'password' => Hash::make($row[2])
]);
}
usersテーブルへのImport
web.phpにusersテーブルへのImportに必要なルーティングを追加します。
Route::resource('/users','UsersController');
UsersControllerのではファイルをアップロードするフォームを表示するindexメソッドとアップロードしたファイルをImportするstoreメソッドを記述しています。
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use App\Imports\UsersImport;
class UsersController extends Controller
{
public function index(){
return view('index');
}
public function store(Request $request){
$file = $request->file('file');
Excel::import(new UsersImport, $file);
}
}
resources¥viewsディレクトリの下にindex.blade.phpファイルを作成します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<form method="POST" action="/users" enctype="multipart/form-data">
{{ csrf_field() }}
<input type="file" id="file" name="file" class="form-control">
<button type="submit">アップロード</button>
</form>
</body>
</html>
/usersにブラウザからアクセスするとファイルをアップロードするため画面が表示されます。

ファイルには下記の内容が記述されたEXCELファイルをアップロードします。

実行後、php artisan tinker等を使用して、usersテーブルの行の情報を確認するとImportした2行の情報が追加されていることを確認することができます。
App\User {#2966
id: "11",
name: "John Dow",
email: "john.dow@example.com",
email_verified_at: null,
created_at: "2018-12-31 12:13:38",
updated_at: "2018-12-31 12:13:38",
},
App\User {#2967
id: "12",
name: "Bill Gate",
email: "bill.gate@example.com",
email_verified_at: null,
created_at: "2018-12-31 12:13:39",
updated_at: "2018-12-31 12:13:39",
},
Export, Importの日本語について
ImportするEXCELファイルに日本語を使用しても文字化けなしでImportすることができます。また、日本語で登録した情報をEXCELファイルでダウンロードすると文字化けなしで行うことができます。