Laravel Excelをマスターしよう
Laravel10.x, Laravel9.x, Laravel8.x, Laravel6.x, Laravel 5.8, 5.7で動作確認を行っています。
Webアプリケーションの規模が大きくなるとサードパーティのアプリケーションから取り出したデータを取り込んだり、Webアプリケーションに保存したデータを他のアプリケーションで取り込むためにCSVファイルのExport/Import機能が必ず必要となります。
CSVファイルだけでなくEXCELファイルでもExport/Importを利用することができればWebアプリケーションを利用するエンドユーザに喜ばれることは間違いありません。データのExport/Emport機能はWebアプリケーションに必須な機能の一つなのでぜひこの機会にLaravel Excelの使い方をマスターしてください。
本文書では、Laravel上でEXCELファイルをExport/Importを行うパッケージLaravel Excelの使用方法について説明を行なっています。本文書を読み終えるとテーブルに保存されているデータをEXCELファイルでダウンロード、または保存することができます。さらにEXCELファイルに保存しているデータを一括でテーブルに保存することができます。
目次
動作確認環境
macOSで動作確認を行っており、Laravelのインストールが完了しデータベースにusersテーブルが存在する環境で行っています。動作確認用のusersテーブルが存在しない場合は下記の手順を参考にusersテーブルを作成してください。
touchコマンドでdatabaseフォルダにdatabase.sqliteファイルを作成。
% touch database/database.sqlite
.envファイルのデータベースの環境設定をsqliteに設定。DB_CONNECTION以外のDB_*は削除。
DB_CONNECTION=sqlite
php artisan migrateコマンドを実行。
% php artisan migrate
Laravel8以降での変更について
Laravel8以降を利用している人はスキップしてください。
Laravel8になりLaravel内部のコードに変更が行われています。その変更のためこれまでのLaravelバージョンとは異なる記述になっています。Laravel Excel側での変更ではありません。
主な違いにLaravel8ではモデルファイルの保存先がappからapp¥Modelsに変更になっています。またweb.phpへのルーティングを設定する際にuseを使ってコントローラーをimportします。Laravel8でのコードも併記して記述しています。
Laravel Excelのインストール
Laravel10の場合
PHPバージョン8.1.6の環境でLaravel10をインストールしてcomposer require maatwebsite/excelコマンドを実行するとバージョンのmaatwebsite/excelの1.1がインストールされました。最新バージョンをインストールするためmaatwebsite/excel:^3.1.48を指定してもエラーが発生。最終的にFlagの-Wをつけると最新版をインストールすることができました。(https://github.com/SpartnerNL/Laravel-Excel/discussions/3726参照)
% composer require maatwebsite/excel:^3.1.48 -W
Laravel 9の場合
Laravel Excelを使用するためにComposerを利用してmaatwebsite/excelのインストールを行います。Laravel9の場合はpsr/simple-cache:^1.0のインストールを行います。Laravelのインストールフォルダで実行してください。
% composer require psr/simple-cache:^1.0 maatwebsite/excel
Laravel8以前の場合以下のコマンドを実行します。
$ 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%)
usersテーブルをEXCELファイルでExport
usersテーブルの中身をEXCELファイルとしてExportするための手順は下記の通りです。usersテーブルにデータが挿入済みであれば数分もかかならいうちにusersテーブルの中身をEXCELファイルとして取得することが可能です。
- Exportファイルの作成
- usersテーブルへのデータの挿入
- Excelファイルのダウンロード
Exportファイルの作成
Laravel Excelを使用してExcelファイルを作成する場合はLaravel ExportのExportクラスを利用します。ExportするExcelファイルへの各種設定(列名の設定やシートの名前)はこのファイルを利用して行うことができデータベースのQueryを記述することができます。
Export用のクラスはphp artisan make:exportコマンドで作成することができます。
usersテーブルに入ったデータをExportしてExcelファイルの作成を行うためmodelオプションでUserを指定して、ファイル名はUsersExportとします。
% php artisan make:export UsersExport --model=User
INFO Export [app/Exports/UsersExport.php] created successfully.
appフォルダの下にExport/UsersExport.phpが作成されます。作成したUsersExport.phpにはcollectionメソッドが記述されています。
<?php
namespace App\Exports;
use App\Models\User; //Laravel8以降の場合
use App\User;//Laravel7以前の場合
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機能を使うことをおすすめします。
テーブルへのデータ挿入
Laravelがデフォルトでusersテーブルへのテストデータへの挿入に関するSeedingの設定を準備してくれているので簡単にデータ挿入を行うことができます。
Laravel8以降の場合にテストデータを挿入したい場合はdatabase¥seeders¥DatabaseSeeder.phpファイルを開いてrunメソッドに入っているコメントを削除します。
create();
// \App\Models\User::factory()->create([
// 'name' => 'Test User',
// 'email' => 'test@example.com',
// ]);
}
}
コメントを外し、php artisan db:seedコマンドを実行するだけでusersテーブルに10件のダミーデータが保存されます。
% php artisan db:seed
INFO Seeding database.
挿入データの確認
usersテーブルにデータが挿入されているかどうかはデータベースの管理ツールを使っても行うことができますがphp artisan tinkerで確認することができます。php artisan tinkerはちょっとしたデータ確認等に役に立つツールです。
% php artisan tinker
Psy Shell v0.11.18 (PHP 8.1.6 — cli) by Justin Hileman
> $users = App\Models\User::all();
= Illuminate\Database\Eloquent\Collection {#7199
all: [
App\Models\User {#7201
id: 1,
name: "Antoinette White",
email: "rowan28@example.net",
email_verified_at: "2023-05-23 23:59:22",
#password: "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
#remember_token: "ax78p4mKic",
created_at: "2023-05-23 23:59:22",
updated_at: "2023-05-23 23:59:22",
},
//略
Laravel7以前の場合は$users = App\User::all();で実行してください。User::all()でも確認できます。
usersテーブルデータのExport
Excelファイルのダウンロード
テーブルへ挿入されているデータが確認できたらExportを実行するコントローラーの作成を行なってください。ここではUsersControllerを作成します。
% php artisan make:controller UsersController
INFO Controller [app/Http/Controllers/UsersController.php] created successfully.
web.phpファイルに作成したUsersControllerコントローラーのルーティングを追加します。
Laravel8以降の場合はweb.phpは下記のようにuseを使ってUsersControllerのパスを記述してください。
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\UsersController;
Route::get('/', function () {
return view('welcome');
});
Route::get('users',[UsersController::class,'export']);
Laravel7以前の場合は下記の通りです。
Route::get('/', function () {
return view('welcome');
});
Route::get('users','UsersController@export');
UsersControllerコントローラーにexportメソッドを記述します。Excelのファサードを利用してdownloadメソッドには、第一引数に作成したUsersExportファイルを指定、第二引数にはファイル名を指定します。exportメソッドが実行されるとusers.xlsxファイルの中にUsersExport内で記述した内容によって取得したデータが保存されダウンロードすることができます。
namespace App\Http\Controllers;
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ファイルがダウンロードフォルダに保存されます。開発環境であればphp artisan serveコマンドでLaravelの起動を忘れずに行ってください。
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; //Laravel7以前の場合
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.html');
}
htmlファイルとして保存することができ、テーブル要素の中にデータを保存します。ファイル内でCSSが適用されているため、あまりきれいには表示されませんが、CSSを変更することで表示は簡単に変更することができます。
Exportableトレイト
ここまでの処理はExcel::downloadを使っていましたがExportableトレイトを使うと実行するコードを下記のように変更することができます。
namespace App\Http\Controllers;
use App\Exports\UsersExport;
class UsersController extends Controller
{
public function export(){
return (new UsersExport)->download('test.xlsx');
}
}
ExportableトレイトはUsersExport.phpファイルで下記のように記述する必要があります。トレイトなのでuseでExportableを指定します。
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を追加することで実現可能です。
Bladeファイルを利用
EXCELファイル内で表示させる内容を設定する際にBladeファイルを利用することができます。Bladeファイルを利用することでEXCELファイル内で表示させる内容をカスタマイズすることができます。
UsersExportファイルではcollectionメソッドを利用していましたがviewメソッドに変更します。viewメソッドに変更することでimportするファイルも変わるので注意してください。viewメソッドの第一引数には利用するBladeファイルを指定します。
namespace App\Exports;
use App\Models\User; //Laravel8の場合
use Maatwebsite\Excel\Concerns\FromView;
use Illuminate\Contracts\View\View;
class UsersExport implements FromView
{
public function view(): View
{
return view('exports.users', [
'users' => User::all()
]);
}
}
UsersControllerの設定はcollectionからviewに変更しても変わりません。
namespace App\Http\Controllers;
use App\Exports\UsersExport;
use Maatwebsite\Excel\Facades\Excel;
class UsersController extends Controller
{
public function export(){
return Excel::download(new UsersExport, 'users.xlsx');
}
}
最後にBladeファイルを追加します。resources¥viewsフォルダにexportsフォルダを作成しその下にusers.blade.phpファイルを作成します。tableタグを利用しています。
<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>
ブラウザから/usersにアクセスすると列にNameとEmailを持つEXCELファイルがダウンロードできます。
さらにEXCELの中にtableタグとは別のタグを利用することでテーブル名を表示させることもできます。
<p>userテーブル</p>
<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>
サーバ上への保存する
テーブルから取り出したデータを保存した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ファイルでダウンロードすると文字化けなしで行うことができます。