Laravel10.x, Laravel9.x, Laravel8.x, Laravel6.x, Laravel 5.8, 5.7で動作確認を行っています。

Webアプリケーションの規模が大きくなるとサードパーティのアプリケーションから取り出したデータを取り込んだり、Webアプリケーションに保存したデータを他のアプリケーションで取り込むためにCSVファイルのExport/Import機能が必ず必要となります。

ExportはLaravelアプリケーションから取得したデータが保存されたファイルをダウンロードすること、Importはデータが保存されたファイルをLaravelアプリケーションにアップロードし変換またはLaravelに保存することを意味します。
fukidashi

CSVファイルだけでなくEXCELファイルでもExport/Importを利用することができればWebアプリケーションを利用するエンドユーザに喜ばれることは間違いありません。データのExport/Emport機能はWebアプリケーションに必須な機能の一つなのでぜひこの機会にLaravel Excelの使い方をマスターしてください。

本文書では、Laravel上でEXCELファイルをExport/Importを行うパッケージLaravel Excelの使用方法について説明を行なっています。本文書を読み終えるとテーブルに保存されているデータをEXCELファイルでダウンロード、または保存することができます。さらにEXCELファイルに保存しているデータを一括でテーブルに保存することができます。

Laravel Excelは名前にExcelが含まれていますがCSVファイルとしても保存することが可能です。
fukidashi

動作確認環境

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%)
maatwebsite/excelはバージョン2からバージョン3にアップデートが行われマニュアルや操作方法も変更になっているので注意が必要です。本文章ではバージョン3について説明を行います。
fukidashi

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コマンドで作成することができます。

php artisan make:exportコマンドはLaravel Exportパッケージをインストールすることで実行できるコマンドです。つまりLaravel Export専用のartisanコマンドです。
fukidashi

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メソッドの中身を変えるだけで対応することができます。

php artsain make:exportコマンドでmodelオプションを設定しなかった場合は、user App\Userとreturn User::all()が記述されていない状態で作成されます。
fukidashi

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テーブルに保存されているすべての行が保存されています。

ダウンロードしたEXCELファイルを開く
ダウンロードしたEXCELファイルを開く

もし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
列名が記述されたEXCEL
列名に日本語を使用することができます。また実際の列とheadingsの列名の数が一致しない場合はエラーにならず、不足した列名は空白で作成されます。
fukidashi

シートに名前をつける

デフォルトでは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を変更することで表示は簡単に変更することができます。

htmlファイルでダウンロード
htmlファイルでダウンロード

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列にはパスワードが入っています。

Importを行うEXCELファイル
Importを行うEXCELファイル

この列情報を元にUsersImport.phpを更新します。

usersテーブルnameには0列、emailには1列、passwordは暗号化を行うので、Hashを使って列2を暗号化しています。

列番号は左から順番に0から番号が振られます。
fukidashi

    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にブラウザからアクセスするとファイルをアップロードするため画面が表示されます。

Importファイルアップデート画面
Importファイルアップデート画面

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

Importを行うEXCELファイル
Importを行う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ファイルでダウンロードすると文字化けなしで行うことができます。