概要
PHP(Laravel)を用いてExcel出力を行う方法を共有します。
以前はPHPExcelが主流みたいでしたが、現在はその後継となるPhpspreadsheetというライブラリが一般的です。
(githubのREADMEにも記載されている通りPHPExcelよりもPhpspreadsheetを使うことが望ましいでしょう。)
今回は社員名簿リストをExcelにて出力します。
ゴールイメージは下記のような感じです。
今回やること
- Excel出力/ブラウザからダウンロード
- 列幅の調整
- 行の固定
環境
PHP 8.1.10
Laravel 9.30.1
1.Phpspreadsheetをインストールする
まずはPhpspreadsheetをインストールします。
composer require phpoffice/phpspreadsheet
2.PhpSpreadsheetクラスの作成
Serviceクラスとして切り出して、新たにExcel出力するファイルを作成します。
(今回はブラウザからダウンロードすることを想定して作成しています。)
app/Services/PhpSpreadsheetService.php
<?php
namespace App\Services;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\IOFactory;
class PhpSpreadsheetService
{
private const HEADER_ROW = 1;
private const BODY_ROW = 2;
private const HEADER_NAMES = [
'社員ID',
'氏名',
'生年月日',
'部署',
'職種',
];
/**
* Excelファイルを出力.
*
* @return void
*/
public function export(): void
{
$this->spreadsheet = new Spreadsheet();
// ヘッダー部分出力
$column_index = range('A', 'Z');
foreach (self::HEADER_NAMES as $key => $header_name) {
$this->spreadsheet->getActiveSheet()->setCellValue($column_index[$key].self::HEADER_ROW, $header_name);
}
// 社員名簿部分出力
$employees = $this->getEmployees();
foreach ($employees as $key => $employee) {
$body_index = 0;
foreach ($employee as $employ_key => $employee_value) {
$this->spreadsheet->getActiveSheet()->setCellValue($column_index[$body_index].(self::BODY_ROW + $key), $employee_value);
$body_index++;
}
}
// 1行目(ヘッダー)を固定
$this->spreadsheet->getActiveSheet()->freezePane('A2');
// 列幅を調整
$this->spreadsheet->getActiveSheet()->getColumnDimension('B')->setWidth(12);
$this->spreadsheet->getActiveSheet()->getColumnDimension('C')->setWidth(12);
$this->spreadsheet->getActiveSheet()->getColumnDimension('D')->setWidth(14);
$this->spreadsheet->getActiveSheet()->getColumnDimension('E')->setWidth(14);
// Excelファイルをダウンロード
$file_name = '社員名簿.xlsx';
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;');
header("Content-Disposition: attachment; filename=\"{$file_name}\"");
header('Cache-Control: max-age=0');
$writer = IOFactory::createWriter($this->spreadsheet, 'Xlsx');
$writer->save('php://output');
exit;
}
/**
* 社員名簿を取得.
*
* @return array
*/
private function getEmployees(): array
{
return [
[
'id' => '1',
'name' => '山田花子',
'birthday' => '1990-01-23',
'department' => '営業部',
'occupation' => '営業',
],
[
'id' => '2',
'name' => '田中太郎',
'birthday' => '1993-08-01',
'department' => '人事部',
'occupation' => '企画',
],
[
'id' => '3',
'name' => '高橋二郎',
'birthday' => '1984-11-01',
'department' => 'システム部',
'occupation' => 'エンジニア',
],
];
}
}
3. 簡易的なダウンロードページ作成
ブラウザからダウンロードできることを想定して、簡易的なダウンロードページを作成します。今回の本目的とは異なるのでCSSは何も充てておりません。ご了承ください。
resources/views/index.blade.php
<html>
<body>
<div>
<form action="{{ url('/download') }}" method="POST">
@csrf
<h2>下記のボタンを押下してExcelファイルをダウンロードしてください。</h2>
<button>download</button>
</form>
</div>
</body>
</html>
ルーティング設定
routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\SpreadsheetController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/index', [SpreadsheetController::class, 'index']);
Route::post('/download', [SpreadsheetController::class, 'download']);
Route::get('/', function () {
return view('welcome');
});
コントローラー側の表示/Excelダウンロード処理
app/Http/Controllers/SpreadsheetController.php
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Services\PhpSpreadsheetService;
use Illuminate\View\View;
class SpreadsheetController extends Controller
{
protected $spreadsheet;
/**
*
* @param PhpSpreadsheetService $spreadsheet
*
* @return void
*/
public function __construct(PhpSpreadsheetService $spreadsheet)
{
$this->spreadsheet = $spreadsheet;
}
/**
* Excelダウンロードページを表示.
*
* @return View
*/
public function index(): View
{
return view('index');
}
/**
* Excelファイルをダウンロード.
*
* @return View
*/
public function download(): View
{
$this->spreadsheet->export();
return view('index');
}
}
4. 動作確認
CSSを充てていないので質素な感じですが、ダウンロードボタンを押します。
Excelを開くとゴールイメージと同じような内容が出力されました。
これにて終了です。