PHPでxlsxファイルをPDFに変換するならLibreOfficeしかないな

こちらはJoolen Advent Calendar 2019 2日目の記事です。
前日の記事は@motuoさんの[EC-CUBE4系(Symfony)のtwigをAjax( jQuery)を使ってValidationしてみた。](https://qiita.com/motuo/items/a6e6cc0d61958dcd9f47)でした。
カレンダーのURLはこちら
[Joolen Advent Calendar 2019](https://qiita.com/advent-calendar/2019/joolen)

# まえがき
最近PHPを使用して、xlsxファイルをPDFに変換する業務がありました。
色々試した結果LibreOfficeに落ち着きました。
その理由を実際に変換した結果とともに書きます。

# 環境
- macOS Mojave
- PHP7.2
- Composer 1.9.1

# PDFへの変換方法の選択肢
そもそもPHPでxlsxをPDFに変換できるのか？
そんな疑問から色々ネットの海を泳いだ結果、以下の情報を得ました。

1. PhpSpreadsheetとDompdfなどを利用して変換する
2. LibreOfficeをインストールして、PHPからコマンドを呼び出す

とりあえずやってみよう!

## 1. PhpSpreadsheetとDompdfなどを利用して変換する
まずはPHPでExcelをファイルを弄れることで有名なPhpSpreadsheetを使用してみます。
PhpSpreadsheetはDompdfの他にmPDFとTCPDFが対応しているので、全て試します。

### 必要なライブラリをインストール

作業ディレクトリはこんな感じです。

```
.
├── composer.json
├── composer.lock
├── src
└── storage
    ├── excel
    └── pdf
```

composerで各種ライブラリインストール

```bash
$ composer require phpoffice/phpspreadsheet
$ composer require dompdf/dompdf
$ composer require mpdf/mpdf
$ composer require tecnickcom/tcpdf
```

composer.jsonを確認

```json:composer.json
{
    (中略)
    "require": {
        "phpoffice/phpspreadsheet": "^1.9",
        "dompdf/dompdf": "^0.8.3",
        "mpdf/mpdf": "^8.0"
        "tecnickcom/tcpdf": "^6.3",
    }
}
```

OK！！

### サンプルエクセルファイル作成

私の手元のPCにはエクセルが入ってないので、Google スプレッドシートで以下の納品書のようなものを作成

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193822/6bd14a96-3150-234c-f991-379b426e0120.png" height="500px">

このファイルを`storage/excel`の中に保存します。

```
.
├── composer.json
├── composer.lock
├── src
└── storage
    ├── excel
    │   └── delivery-note.xlsx <- 作成したエクセルファイル
    └── pdf
```

### コードを書く:computer:

```php:src/xlsx-to-pdf.php
<?php
require __DIR__ . '/../vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\IOFactory;

$orderNote = __DIR__ . '/../storage/excel/order-note.xlsx';
echo "load: $orderNote", PHP_EOL;

$reader = IOFactory::createReader('Xlsx');
$spreadsheet = $reader->load($orderNote);

// Dompdfを使用してエクスポート
outputPdf($spreadsheet, 'Dompdf');

// mPDFを使用してエクスポート
outputPdf($spreadsheet, 'Mpdf');

// TCPDFを使用してエクスポート
outputPdf($spreadsheet, 'Tcpdf');

function outputPdf($spreadsheet, $writerType) {
    $writer = IOFactory::createWriter($spreadsheet, ucfirst(strtolower($writerType)));
    $writer->save(__DIR__ . '/../storage/pdf/' . strtolower($writerType) . '.pdf');
}
```

実行した結果PDFファイルが追加されました。
中身を見てみましょう。

#### Dompdf
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193822/b7a070e8-c42b-3498-1127-c87c7449403d.png" height="600px">

#### mPDF
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193822/66c4863e-295c-6411-22c7-0a033238a828.png" height="600px">

#### TCPDF
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193822/c3fa08cd-4eab-8a9a-ca77-e6f14e7a303d.png" height="600px">

:thinking: :thinking: :thinking:

TCPDFの驚きの白さ。
DompdfとmPDFは文字化けと印刷設定でなんとかなるかもしれないですね。罫線が一部消えてるのが気になりますが。。。
この後文字化け対策でフォント入れようとしたのですが、上手く出来ませんでした。
知っている方いれば教えてください。。。

## 2. LibreOfficeをインストールして、PHPからコマンドを呼び出す
LibreOfficeは無料で使えるオフィスソフトです。
コマンドラインからも色々な操作ができるので、それを利用してxlsxをPDFに変換します。

### LibreOfficeのインストール
下記のURLからインストールします。
https://ja.libreoffice.org/download/download/

Linuxの場合はyumやapt-getにあると思います。

### コードを書く:computer:

先ほど書いたコードにLibreOfficeを使用して変換する処理を追加します.

```php:src/xlsx-to-pdf.php
<?php
require __DIR__ . '/../vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\IOFactory;

$orderNote = __DIR__ . '/../storage/excel/order-note.xlsx';
echo "load: $orderNote", PHP_EOL;

(中略)

// LibreOfficeを使用してエクスポート
$soffice = '/Applications/LibreOffice.app/Contents/MacOS/soffice';
$command = "$soffice --headless --convert-to pdf --outdir " . __DIR__ . "/../storage/pdf $orderNote";
echo $command, PHP_EOL;
exec($command);
```

実行してみましょう。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193822/6939f47e-a8a2-66bb-d01c-29edaf865f58.png" height="600px">

悪くないですが、高さの自動調整が効いてないですね。
LibreOfficeはシステムフォントを利用するようなので、Linuxでも日本語化は苦ではない。


PhpSpreadsheetとLibreOfficeを使用してPDF変換した結果は以上です。

## まとめ
- LibreOfficeは高さの自動調整だけ気をつければ大丈夫そう
- 日本語化できるならPhpSpreadsheetも使えるかも
- そもそもPHPでxlsxをPDFに変換するのは向いてない
- どうしてもやるならLibreOfficeが一番楽で綺麗

以上です。
明日は@hwatryさんの[TS初心者がハマった初歩の初歩](https://qiita.com/hwatry/items/b2c0446a4681d8c41d92)です。