PHPExcel 1.8以上でPDF出力すると「Error – PDF Rendering library has not been defined」

PHPExcel で Excel から PDF に変換して出力する際に、「Error – PDF Rendering library has not been defined」とエラーになったので、そのときの備忘録です。

PHPExcel1.8.0を使用しました。

  

PHPExcel

旧サイトから GitHub に移行した様子。

PHPExcel は PHP から Excel を出力するライブラリです。
サーバに Excel のインストールは必要はありません。

メモリを大量に消費するためメモリーオーバーにもなりやすいですが、よく使われているライブラリでもあります。

環境

  • PHPExcel 1.8.0

最新バージョンは1.8.2(2017/07/31現在)

PDF出力を試みる

header('Content-Type: application/octet-stream');
header("Content-Disposition: attachment; filename*=UTF-8''" . rawurlencode($filename) . "_" . date("YmdHis") . ".pdf");
header('Cache-Control: max-age=0');
ob_end_clean();
$writer = PHPExcel_IOFactory::createWriter($this->phpexcel, 'PDF');
$writer->save('php://output');

PHPExcel_Writer_PDF クラスが存在するので、PHPExcel_IOFactory::createWriter の引数に ‘PDF’ を指定するも、以下のエラーになります。

Error - PDF Rendering library has not been defined

検索すると PHPExcel1.8だとPDF作成できないみたいなコメントがあるがこれは誤りです。

参照元サイト を見ると

1.7.4から1.8.0の間にいくつかの変更が加えられたためです。PHPExcel にバンドルされていない PDF レンダリングライブラリは、tcPDF、mPDF、または DomPDF の独自の選択肢を自由に選択してインストールし、ライブラリ、例とドキュメントで説明されています。

と回答がついています。

PDF へ変換するライブラリは3つから選択できます。

PHPExcel の Example を覗く

//  Change these values to select the Rendering library that you wish to use
//      and its directory location on your server
//$rendererName = PHPExcel_Settings::PDF_RENDERER_TCPDF;
//$rendererName = PHPExcel_Settings::PDF_RENDERER_MPDF;
$rendererName = PHPExcel_Settings::PDF_RENDERER_DOMPDF;
//$rendererLibrary = 'tcPDF5.9';
//$rendererLibrary = 'mPDF5.4';
$rendererLibrary = 'domPDF0.6.0beta3';
$rendererLibraryPath = '/php/libraries/PDF/' . $rendererLibrary;
echo date('H:i:s') , " Hide grid lines" , EOL;
$objPHPExcel->getActiveSheet()->setShowGridLines(false);
echo date('H:i:s') , " Set orientation to landscape" , EOL;
$objPHPExcel->getActiveSheet()->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE);
echo date('H:i:s') , " Write to PDF format using {$rendererName}" , EOL;
if (!PHPExcel_Settings::setPdfRenderer(
        $rendererName,
        $rendererLibraryPath
    )) {
    die(
        'NOTICE: Please set the $rendererName and $rendererLibraryPath values' .
        EOL .
        'at the top of this script as appropriate for your directory structure'
    );
}

PHP Excel の例を見ると、ライブラリ名と、ライブラリのパスを指定していることがわかります。

この例で DomPDF を使用していることと、GitHub のスターの数を理由に今回は DomPDF を選択します。

ちなみに DomPDF もバージョンアップしているので、この例のままではうまくいかない場合があります。

$rendererName = PHPExcel_Settings::PDF_RENDERER_DOMPDF;
$rendererLibraryPath = APPPATH . 'vendor/dompdf/';

PHPExcel_Settings::setPdfRenderer(
  $rendererName,
  $rendererLibraryPath
);

header('Content-Type: application/octet-stream');
header("Content-Disposition: attachment; filename*=UTF-8''" . rawurlencode($filename) . "_" . date("YmdHis") . ".pdf");
header('Cache-Control: max-age=0');
ob_end_clean();
$writer = PHPExcel_IOFactory::createWriter($this->phpexcel, 'PDF');
$writer->save('php://output');

PHPExcel_Settings::setPdfRenderer でライブラリ名とライブラリへのパスを指定し設定したものの以下のエラーになります。

Fatal Error - Class 'DOMPDF' not found

これは最新の DomPDF が namespace(PHP5.3以上の機能)を使用しているためだと思われます。

DomPDF のリポジトリを見ると、ファイルの読み込みは以下のようになっています。

require_once 'dompdf/autoload.inc.php';

また、namespace も指定しています。

use Dompdf\Dompdf;
$dompdf = new Dompdf();

PHPExcel\Classes\PHPExcel\Writer\PDF\DomPDF.php の以下の部分を修正します。

修正前

/**  Require DomPDF library */
$pdfRendererClassFile = PHPExcel_Settings::getPdfRendererPath() . '/dompdf_config.inc.php';

修正後

/**  Require DomPDF library */
use Dompdf\Dompdf;
$pdfRendererClassFile = PHPExcel_Settings::getPdfRendererPath() . '/autoload.inc.php';

ライブラリのコアに手を加えるのは望ましくないですが、ここまで修正して PDF 出力が可能にななりました。

PDF 変換を使用してみて

  • Excel からの変換は期待しているような表示にはならない。HTML からの変換の方がレイアウトは崩れないのではないかと予想。
  • 日本語が文字化けするようなので、対策が必要。
  • とにかく重い。Excel 処理だけでも重いので、実用できるようなレベルではないように思える。
  • LibreOffice をインストールするとコマンドで PDF に変換できるので、そちらのほうが使えるかもしれない。
  

共有やブックマークなど