勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

PHPでテンプレートPDFに動的に文字や数値を追記し出力する方法(TCPDF&FPDI)

   2024/01/12  PHP

請求書や領収書のテンプレートがあり、そちらに対して動的に文字・数値を追記し出力させるというシステムを実装したかった。以前にHTML / CSSで作成したページをPDF化するという記事を書いたが、こちらでは見た目がシンプルすぎて業務で使うには微妙。何か方法は無いかと探したところTCPDF&FPDIの組み合わせが良さそうだったので以下に実装方法をメモ。

 

TCPDF

以下からダウンロードし展開したものを適当なディレクトリにアップロードする。

https://github.com/tecnickcom/tcpdf

尚、非公式とのことだが以下リファレンスが日本語で見やすい。

http://tcpdf.penlabo.net/

また、必須では無いが今回はフォントを「arialunicid0」に指定したいため過去記事を参考の上で該当ファイルをアップロードしておく。

 

FPDI

以下からダウンロードし展開したものを適当なディレクトリにアップロードする。

https://www.setasign.com/products/fpdi/downloads/

 

テンプレートの用意

今回はテストのため以下のようなテンプレートサイトからエクセルファイルをダウンロードし、PDF化した上で適当なディレクトリにアップロードしておく。

https://template.the-board.jp/receipt_templates/article/receipt_template_001

ちなみに今回用意したテスト用PDFは以下の通り。

https://taitan916.info/sample/pdf/test/test.pdf

 

ソースコード

<?php
//TCPDF&FPDIの読み込み
include('./tcpdf/tcpdf.php');
include('./fpdi/autoload.php');

$flg = false;

do{

    if( !$_GET['name'] || !$_GET['price'] ){
        break;
    }

    //TCPDFオブジェクト作成
    $pdf = new setasign\Fpdi\Tcpdf\Fpdi();

    //余白無し
    $pdf->SetMargins(0, 0, 0);

    //自動で改ページさせない
    $pdf->SetAutoPageBreak(false, 0);

    //ヘッダーフッター無し
    $pdf->setPrintHeader( false );
    $pdf->setPrintFooter( false );

    //テンプレートPDF読み込み
    $pdf->setSourceFile('./test.pdf');

    //新ページを作成
    $pdf->AddPage();

    //読み込んだPDFの1ページ目を取得
    $tpl = $pdf->importPage(1);
    $pdf->useTemplate($tpl, null, null, null, null, true);

    //通常フォントサイズ設定
    $pdf->SetFont('arialunicid0', '', 17);

    //宛名
    $pdf->Text(15, 34, htmlspecialchars( $_GET['name'] ) );

    //金額
    $pdf->Text(70, 57, htmlspecialchars( number_format($_GET['price']) ) );

    $pdf->Output("output.pdf", "I");

}while(0);

?>

上記は領収書の宛名と金額をGETパラメータで受け取り、出力するという内容のソースコードになる。サンプルのためバリデートや例外処理は適当なため、本番実装時はその辺りを適宜変更する。念のため以下サンプルページとなる。

https://taitan916.info/sample/pdf/test/?name=%E3%81%82%E3%81%82%E3%81%82&price=10000

 

使用感など

自動改行は難しい

見積書などを発行する際に商品名が長く、改行したいというケースがあった。ただ文字数に応じて自動で改行するというのは難しい(方法はあるかもしれないが見つけられなかった)。

そのため商品名を出力する前に「何文字以上の場合は改行」という処理をPHP側で行わざるを得なかった。

テンプレートの注意点

見積書などで商品名を複数記載する可能性があるような場合、こちらのような1行ずつ仕切られているようなテンプレートよりも、こちらのように仕切られていないテンプレートの方が使いやすい。

というのも1行ずつ仕切られているテンプレートで、長い商品名を記述する場合に改行且つ文字サイズを小さくする必要が出てくる。そうすると見づらくなる上に処理が面倒臭くなる。

仕切られていなければ改行処理は必要なものの文字サイズの調整は不要なので楽。

複数ページに渡る場合

見積書などで商品数自体が多く、1ページでは足りないケースがあった。1枚のPDFで複数ページを発行というのもできそうではあるが、その場合は2ページ目以降のテンプレートファイルも必要になりそう。

そのため、商品数が多くなる場合は複数枚のPDFファイルを発行し、zip圧縮した上でダウンロードさせる形を取った。

文字の右寄せ、中央寄せは難しい

左寄せは簡単だけど右・中央寄せは難しい(方法はあるかもしれないが見つけられなかった)。ただ請求書番号とか数値に関してはゼロ詰めにして桁数をあらかじめ決めておけばできなくはない。

 

所感

色々と制限はあるもののテンプレートファイルさえ用意すればそれなりの見た目になるので業務で十分に使えそう。

 - PHP

  関連記事

TCPDF「Could not include font definition」エラーの対処方法

TCPDFでフォントを「arialunicid0」に指定したところ「TCPDF ...

PHPでパスワード付きのZIP / PDFファイルを作成する方法

PHPでZIPファイル化する方法やPDFファイル出力する方法を過去に書いたが、何 ...

FPDIで「This PDF document probably uses~~」エラーの対処方法

FPIDであるPDFを読み込ませようとすると「This PDF document ...

HTML / CSSで作成したコンテンツをPDFファイルで出力する方法(TCPDF)

HTML / CSSで作成したコンテンツをPDFファイルで出力させたい。以前mp ...

mpdfで「The /e modifier is …」エラー発生時の対応方法

pdf関連のPHPライブラリ「mPDF」を使っているページがエラーログにのってお ...