本記事では、生成済みのExcelファイルをLaravelのMPdfを使用してPDFファイルへ変換する方法について記載します

Mpdfのインストール

まず、Composer を使って MPdf をプロジェクトに追加します。ターミナルで以下のコマンドを実行:

composer require mpdf/mpdf

これにより、Composer が mPDF をダウンロードしてインストールします。
※ LaravelプロジェクトにまだPhpSpreadsheetを導入していない場合は、合わせて下記のコマンドでインストールしてください。

composer require phpoffice/phpspreadsheet

PDF出力時に使用するクラスの作成

mPDFの基本設定やカスタム設定を管理するため、BaseMpdfを継承したクラスを作成します。

php

class MyCustomMpdfWriter extends BaseMpdf
{
    protected function createExternalWriterInstance($config): Mpdf
    {
        // (1) デフォルト設定を取得
        $configVariables = (new ConfigVariables())->getDefaults();
        $fontDirs = $configVariables['fontDir'];

        $fontVariables = (new FontVariables())->getDefaults();
        $fontData = $fontVariables['fontdata'];

        // (2) デフォルトのフォント設定に日本語フォントを追加
        $defaultConfig = [
            'fontDir' => array_merge($fontDirs, [
                resource_path('views/xlxs/fonts'), // 日本語フォントのパス
            ]),
            'fontdata' => $fontData + [
                'ipaexg' => [ // IPAexゴシックフォント
                    'R' => 'ipaexg.ttf', // 通常
                    'B' => 'ipaexg.ttf', // 太字
                ],
            ],
            'default_font' => 'xxxx', // デフォルトフォントを日本語に設定
            'margin_top' => 0,         // 上の余白
            'margin_bottom' => 0,      // 下の余白
            'margin_left' => 0,        // 左の余白
            'margin_right' => 0,       // 右の余白
            'margin_header' => 0,       // ヘッダーの余白
            'margin_footer' => 0,       // フッターの余白
            'format' => 'A4',           // 用紙サイズ
        ];

        // (3) カスタム設定をマージしてインスタンスを生成
        $finalConfig = array_merge($defaultConfig, $config);
        $mpdf = new Mpdf($finalConfig);
        $mpdf->SetMargins(0, 0, 0); // 左、上、右のマージン
        $mpdf->SetAutoPageBreak(true, 0);
        $mpdf->debug = true;

        return $mpdf;
    }

    /**
     * Save Spreadsheet to file.
     *
     * @param string $filename Name of the file to save as
     */
    public function save($filename, int $flags = 0): void
    {
        $fileHandle = parent::prepareForSave($filename);

        //  Check for paper size and page orientation
        $setup = $this->spreadsheet->getSheet($this->getSheetIndex() ?? 0)->getPageSetup();
        $orientation = $this->getOrientation() ?? $setup->getOrientation();
        $orientation = ($orientation === PageSetup::ORIENTATION_LANDSCAPE) ? 'L' : 'P';
        $printPaperSize = $this->getPaperSize() ?? $setup->getPaperSize();
        $paperSize = self::$paperSizes[$printPaperSize] ?? PageSetup::getPaperSizeDefault();

        //  Create PDF
        $config = ['tempDir' => $this->tempDir . '/mpdf'];
        $pdf = $this->createExternalWriterInstance($config);
        $ortmp = $orientation;
        $pdf->_setPageSize($paperSize, $ortmp);
        $pdf->DefOrientation = $orientation;
        $pdf->AddPageByArray([
            'orientation' => $orientation,
            'margin-left' => 0,
            'margin-right' => 0,
            'margin-top' => 0,
            'margin-bottom' => 0,
        ]);

        //  Document info
        $pdf->SetTitle($this->spreadsheet->getProperties()->getTitle());
        $pdf->SetAuthor($this->spreadsheet->getProperties()->getCreator());
        $pdf->SetSubject($this->spreadsheet->getProperties()->getSubject());
        $pdf->SetKeywords($this->spreadsheet->getProperties()->getKeywords());
        $pdf->SetCreator($this->spreadsheet->getProperties()->getCreator());

        $html = $this->generateHTMLAll();
        // 画像をBase64エンコードする
        $imagePath = public_path('img/xxxxxx.png');
        $imageData = base64_encode(file_get_contents($imagePath));
        $imageMime = mime_content_type($imagePath);
        // imgタグをBase64で埋め込む
        $imgTag = '<img src="data:' . $imageMime . ';base64,' . $imageData . '" alt="img Image" style="width: 103px; height: 95px;">';
        $html = str_ireplace('img', $imgTag, $html);
        $bodyLocation = strpos($html, Html::BODY_LINE);
        // Make sure first data presented to Mpdf includes body tag
        //   so that Mpdf doesn't parse it as content. Issue 2432.
        if ($bodyLocation !== false) {
            $bodyLocation += strlen(Html::BODY_LINE);
            $pdf->WriteHTML(substr($html, 0, $bodyLocation));
            $html = substr($html, $bodyLocation);
        }
        foreach (\array_chunk(\explode(PHP_EOL, $html), 1000) as $lines) {
            $pdf->WriteHTML(\implode(PHP_EOL, $lines));
        }

        //  Write to file
        fwrite($fileHandle, $pdf->Output('', 'S'));

        parent::restoreStateAfterSave();
    }

このクラスを継承して使用することで、各コントローラーやサービス内でmPDFの初期化時に設定を簡単に反映させることができます。
※ 設定内容はプロジェクトの要件に合わせて適宜変更してください。
※フォントについてはダウンロードを行いプロジェクト内に配置しパスを指定することで使用できます。

画像の埋め込み

上記のsave関数では下になるExcelファイルのセルに特定の文字列がある場合、
それを画像に置き換える処理を記載しています。
Excelに画像が埋め込まれていても、PDF変換時には引き継がれないため
該当のセルに判別用の文字を記入して、PDFへの変換時に画像の埋め込みを行います。

今回は継承したBaseMpdfのsave関数の中で画像の埋め込み処理を行いました。

ExcelファイルからPDFへの変換

先ほど作成したMyCustomMpdfWriterを使用してMPdfの設定を反映し、
出力を行います。
以下は、コントローラー内でのサンプルコードです。

public function exportToPdf()
{
    $spreadsheet = IOFactory::load($this->templatePath);

    // 継承したクラスを new する
    $writer = new MyCustomMpdfWriter($spreadsheet);

    // 一時保存用excelファイルのファイル名作成
    $timestamp = now()->format('Ymd');
    $exportFilePath = "app/public/export.pdf";

    // PDFファイルを保存
    $pdfPath = storage_path($exportFilePath);
    $writer->save($pdfPath);

    return $pdfPath;
}

変換時の注意点

ExcelファイルからPDFへの変換には、いくつか注意すべきポイントがあります。

  • 複数シートの対応
    Excelファイルに複数のシートが含まれている場合、どのシートを変換対象とするかを明確にする必要があります。上記の例ではデフォルトのシートを対象としていますが、必要に応じてシートの選択ロジックを実装してください。
  • スタイルやフォーマットの調整
    PhpSpreadsheetのHTMLライターは、Excelの全てのスタイルやフォーマットを完全に再現できない場合があります。特に、セルの結合や特殊なフォント、色などは再調整が必要になることがあるため、生成後のHTMLを確認し、適宜カスタマイズすることをおすすめします。
  • パフォーマンスとメモリの消費
    大容量のExcelファイルを変換する場合、メモリ消費量が増大する可能性があります。mPDFおよびPhpSpreadsheetの設定でメモリ制限やタイムアウトの対策を検討してください。
  • セキュリティ対策
    ユーザーからアップロードされたファイルを扱う際は、ファイルの種類や内容の検証、またアップロードディレクトリの適切な管理など、セキュリティ面の対策を十分に行いましょう。

まとめ

本記事では、Laravel環境において、生成済みのExcelファイルをmPDFを用いてPDFファイルに変換する方法について解説しました。
大まかな流れは以下の通りです。

  • mPDF(および必要に応じてPhpSpreadsheet)のインストール
    Composerを利用して各ライブラリをインストールします。
  • PDF出力用の設定ファイル作成
    プロジェクトごとにPDF出力の初期設定をまとめた設定ファイルを用意し、管理しやすくします。
  • mPDFでのPDF生成と出力
    変換したHTMLをmPDFに渡し、PDFを生成してブラウザに出力します。
  • 変換時の注意点の確認
    複数シートへの対応、スタイル調整、パフォーマンス、セキュリティ面に注意しながら実装を進めます。

この手法を活用することで、Excelファイルの内容を手軽にPDF化することができます。