PHPでエクセルファイルを作成し、PDFとして出力する。(1)

2022/07/29
高橋

こんにちは。株式会社リンクネット、ソリューション事業部の高橋です。

弊社ではWebシステムバックエンドにLaravelを利用しています。
エクセルのファイル(.xlsx)をPHPで操作しPDFファイルとして出力した際に、
レイアウトが崩れる場合や、日本語が表示されないといった想定外の問題が発生しました。
この記事では、上記の問題を解消した方法を共有します。

環境

$ sail artisan -V
Laravel Framework 8.82.0
$ sail php -v
PHP 8.1.5 (cli) (built: Apr 21 2022 10:15:06) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.5, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.5, Copyright (c), by Zend Technologies
    with Xdebug v3.1.2, Copyright (c) 2002-2021, by Derick Rethans

エクセルファイルの操作について

エクセルファイルを操作する方法としましてはPhpSpreadsheetを選定しました。
本記事ではインストール方法については省略します。

https://github.com/PHPOffice/PhpSpreadsheet

今回、使用するエクセルファイルは下記になります。
https://www.microsoft.com/ja-jp/office/pipc/template/result.aspx?id=13281

01 exeel format
  1. ベースとなるエクセルファイルを読み込む

        $public_path = public_path('excel/sample_format.xlsx'); //サンプルファイルのPATHを取得
        $file_name = 'example';
        $tmp_path = storage_path('app/example');
        $tmp_xlsx_path = $tmp_path.'/'.$file_name.'.xlsx';
        $tmp_pdf_path = $tmp_path.'/'.$file_name.'.pdf';
    
        $xr = new XReader(); //PhpSpreadsheetのClass
        $xr->setReadDataOnly(false); //これをfalseにしないと複写できない
        $spread = $xr->load($public_path); //エクセルファイルの読み込み
        $sheet = $spread->getActivesheet();//現在選択中のシートの読み込み
  2. エクセルファイルの任意のセルに値を代入する。

        //エクセルファイルのセルに値を代入
        $sheet->setCellValue('B6', 'サンプル株式会社');
  3. エクセルファイルの保存

      $sheet->getPageSetup()->setPrintArea('A1:F58');//印刷範囲
      $sheet->getPageSetup()->setScale(90);//印刷時の倍率
      $sheet->getPageSetup()->setPaperSize(PageSetup::PAPERSIZE_A4); //A4サイズ
      //xlsxファイルを出力
      $writer = new XlsxWriter($spread);
      $writer->save($tmp_xlsx_path);

    出力されたxlsxファイル ※B6にサンプル株式会社と入力されています。
    02 output excel format

  4. PDFファイルとして出力する。

    1. PhpSpreadsheetの機能でPDFへ変換する。

      $Xw = IOF::createWriter($spread,'Tcpdf'); //IOFactoryで作成する
      $Xw->setFont('kozgopromedium'); //作成したオブジェクトにフォント設定をする(小塚ゴシック)
      $Xw->save($tmp_pdf_path); //保存する

      出力されたPDFファイル ※PhpSpreadsheetで出力されたPDFはレイアウトが崩れてしまいます。
      PHPでの出力方法が他にないか調査したところDompdfTCPDFmPDFが候補にあがりましたが、
      やはりレイアウトが崩れてしまうようです。
      PHPで変換するよりはlibreofficeで変換するほうがレイアウトが崩れないようです。
      参考サイト:

      https://qiita.com/Hiro2525/items/2bab16f5d9318762e2fd

      03 output pdf io
    2. libreofficeの機能でPDFへ変換する。
      libreofficeのインストール
      参考サイト:
      https://www.kkaneko.jp/tools/ubuntu/libreofficejaubuntu.html

      開発環境ではsailを使用しているため、sail shellで libreofficeをインストールします。

      1. root権限でsail shellにログインし、libreofficeをインストールする。

        $ sail root-shell
        root@b74b851b5064:/var/www/html#apt -y update
        root@b74b851b5064:/var/www/html#apt -y install libreoffice libreoffice-l10n-ja libreoffice-dmaths libreoffice-ogltrans libreoffice-writer2xhtml libreoffice-pdfimport libreoffice-help-ja
      2. PHPではlibreofficeのコマンドを実行して.xlsxファイルをPDFへ変換します。

        //libreofficeでxlsxファイルをpdfに出力
        $command = '/usr/bin/soffice --headless --convert-to pdf --outdir '.$tmp_path.' '.$tmp_xlsx_path;
        
        exec($command);

      出力されたPDFファイル ※レイアウトはきれいに出力されましたが、日本語が文字化けしています。
      おそらく、 libreofficeに日本語フォントが登録されていないと推測できたので、
      調査したところ、下記のサイトで導入方法が見つかりました。
      今回はIPAフォントを選択しました。

      参考サイト:
      https://lab4ict.com/system/archives/879

      04 output pdf soffice
    3. 日本語フォントを登録する。
      root権限でsail shellにログインし、日本語フォントを登録する

      $ sail root-shell
      root@b74b851b5064:/var/www/html#apt install fonts-ipafont fonts-ipaexfont
      root@b74b851b5064:/var/www/html#fc-cache -fv

      出力されたPDFファイル ※日本語も表示されました。

      05 output pdf soffice ja

課題

今回、紹介しました方法では、dockerコンテナを起動する度に、
sail shellでのlibreofficeや日本語フォントのインストールが必要となります。
そのため、自動でインストールできる仕組みの構築が課題となります。

前の記事次の記事