- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2018-09-30T06:51:07+00:00","","")
* TCPDFでPDF帳票の作成 [#j23de1e5]
#setlinebreak(on);
PHPライブラリ [[TCPDF>https://tcpdf.org/]] でPDF帳票を作成する手順を記載する。
利用方法はいくつか考えられるが、実運用で使えそうな [[HTML->PDF変換>#va993123]]、[[テンプレートPDFへの値埋め込み>#rd36ac9d]] だけ記載する。
//- [[HTMLをPDFに変換して出力する>#va993123]]
//- [[既存のPDFテンプレートに値を埋め込んで出力する>#rd36ac9d]]
#contents
-- 参考
--- https://tcpdf.org/
--- https://www.setasign.com/products/fpdi/
** インストール [#t0ee2a3e]
#html(<div style="padding-left:10px">)
たぶん Composer でやる方が良いが。。
** 適当なフォルダを作る [#n0661f21]
#html(<div style="padding-left:10px">)
#myterm2(){{
mkdir test-tcpdf
cd test-tcpdf
}}
#html(</div>)
** TCPDFインストール [#u684149f]
#html(<div style="padding-left:10px">)
https://github.com/tecnickcom/tcpdf から git clone
#myterm2(){{
git clone https://github.com/tecnickcom/TCPDF.git
}}
#html(</div>)
** FPDIインストール [#y91532e4]
#html(<div style="padding-left:10px">)
PDFをテンプレートにして値を埋め込む場合は必須
https://www.setasign.com/products/fpdi/downloads/
#myterm2(){{
mkdir FPDI && cd FPDI
wget https://www.setasign.com/downloads/2102915/FPDI-2.1.0.zip
unzip FPDI-2.1.0.zip
rm -rf FPDI-2.1.0.zip
cd ../
}}
#html(</div>)
** インストール後のフォルダ構成 [#u4d864a6]
#html(<div style="padding-left:10px">)
だいたいこんな感じ。
#myterm2(){{
test-tcpdf
├── FPDI
│   ├── LICENSE.txt
│   ├── README.md
│   ├── composer.json
│   └── src
│   ├── FpdfTpl.php
│   ├── FpdfTplTrait.php
│   ├── Fpdi.php
│   ├── FpdiException.php
│   ├── FpdiTrait.php
│   ├── PdfParser
│   ├── PdfReader
│   ├── Tcpdf
│   ├── TcpdfFpdi.php
│   ├── Tfpdf
│   └── autoload.php
├── TCPDF
│   ├── CHANGELOG.TXT
│   ├── LICENSE.TXT
│   ├── README.md
│   ├── composer.json
│   ├── config
│   ├── examples
│   ├── fonts
│   ├── include
│   ├── tcpdf.php
│   ├── tcpdf_autoconfig.php
│   ├── tcpdf_barcodes_1d.php
│   ├── tcpdf_barcodes_2d.php
│   ├── tcpdf_import.php
│   ├── tcpdf_parser.php
│   └── tools
}}
#html(</div>)
#html(</div>)
// インストール END
** HTMLからPDFを出力する [#va993123]
#html(<div style="padding-left:10px">)
スタイルシートも効くが、padding が効かない等、いくつかの制限がある模様。
html2pdf.php
#mycode2(){{
<?php
include("./TCPDF/tcpdf.php");
define("MY_PDF_PAGE_ORIENTATION" , "P"); // P:Portrait, L:Landscape
define("MY_PDF_FONT_NAME" , "kozgopromedium"); // kozminproregular
define("MY_PDF_FONT_SIZE" , 10);
define("MY_PDF_UNIT" , "mm");
define("MY_PDF_PAGE_FORMAT" , "A4");
define("MY_PDF_IMAGE_SCALE_RATIO" , 1);
define("MY_PDF_MARGIN_HEADER" , 0);
define("MY_PDF_MARGIN_FOOTER" , 0);
define("MY_PDF_MARGIN_TOP" , 10);
define("MY_PDF_MARGIN_LEFT" , 15);
define("MY_PDF_MARGIN_RIGHT" , 15);
define("MY_PDF_MARGIN_BOTTOM" , 20);
class MYPDF extends TCPDF {
// フッタのカスタマイズ(ページ番号を出力する)
public function Footer() {
$this->SetY(-15); // Position at 15 mm from bottom
$this->SetFont('helvetica', 'I', 8);
$this->Cell(0, 10, 'Page '.$this->getAliasNumPage().'/'.$this->getAliasNbPages(), 0, false, 'C', 0, '', 0, false, 'T', 'M');
}
}
$pdf = new MYPDF(MY_PDF_PAGE_ORIENTATION, MY_PDF_UNIT, MY_PDF_PAGE_FORMAT, true, 'UTF-8', false);
$pdf->SetTitle('PDF出力テスト');
//$pdf->SetSubject('TCPDF Tutorial');
//$pdf->SetHeaderData(null, null, null, null);
//$pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, PDF_HEADER_TITLE.' 006', PDF_HEADER_STRING);
//$pdf->setHeaderFont(Array(MY_PDF_FONT_NAME, '', MY_PDF_FONT_SIZE));
//$pdf->setFooterFont(Array(MY_PDF_FONT_NAME, '', MY_PDF_FONT_SIZE));
//$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
$pdf->SetMargins(MY_PDF_MARGIN_LEFT, MY_PDF_MARGIN_TOP, MY_PDF_MARGIN_RIGHT);
//$pdf->SetHeaderMargin(MY_PDF_MARGIN_HEADER);
//$pdf->SetFooterMargin(MY_PDF_MARGIN_FOOTER);
$pdf->SetAutoPageBreak(TRUE, MY_PDF_MARGIN_BOTTOM);
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(true);
$pdf->setImageScale(MY_PDF_IMAGE_SCALE_RATIO);
$pdf->SetFont(MY_PDF_FONT_NAME, "", 10);
// ページを追加
$pdf->AddPage();
// PDFに変換するHTML
$html =<<<_EO_HTML_
<style>
table {
border-collapse: collapse;
}
table tr th {
background-color: #efe;
border: 1px solid #333;
padding: 10px; /* 効かない */
}
table tr td {
border: 1px solid #333;
padding: 10px; /* 効かない */
}
.center {
text-align: center;
}
</style>
<h1>TCPDFテスト</h1>
<table cellpadding="5">
<thead>
<tr>
<th>列1</th><th>列2</th><th>列3</th>
</tr>
</thead>
<tbody>
<tr>
<td>2018-01-01</td><td>テスト1</td><td class="center">100</td>
</tr>
<tr>
<td>2018-01-02</td><td>テスト2</td><td class="center">200</td>
</tr>
</tbody>
</table>
_EO_HTML_;
$pdf->writeHTML($html, true, false, true, false, '');
// 2ページ目追加
//$pdf->lastPage();
//$pdf->AddPage();
//$pdf->writeHTML($html, true, false, true, false, '');
/*
* Output の第2引数にI,D,FI,FD を指定すればHTTPレスポンスヘッダ(Content-TypeやContent-Disposition)を自動的に出力してくれる。
* 自分でヘッダを調整したい場合は、S でデータだけ取得して自分でヘッダを吐く。
* (ファイル名に日本語を含めたい場合など.)
*/
$data = null;
$fileName = "テスト.pdf";
//$pdf->Output($fileName, 'I'); // ブラウザに表示
//$pdf->Output($fileName, 'D'); // ダウンロードダイアログを表示
//$pdf->Output($fileName, 'F'); // サーバにファイルを保存
$data = $pdf->Output(null,'S'); // PDFドキュメントを文字列として返却
//$pdf->Output($fileName, 'FI'); // ファイルに保存して、ブラウザにも表示
//$pdf->Output($fileName, 'FD'); // ファイルに保存して、ダウンロードダイアログを表示
//$data = $pdf->Output(null, 'E'); // Base64エンコード済みのPDFドキュメントを返却(メールに添付するmultipartコンテンツ用なのでContent-Typeなどのヘッダーが付く)
if ($data != null) {
// ブラウザにそのまま表示
header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="'.basename($fileName).'"');
// ダウンロード
//header('Content-Type: application/octet-stream', false);
//header('Content-Disposition: attachment; filename="'.basename($fileName).'"');
echo $data;
}
?>
}}
#html(</div>)
** 既存のPDFテンプレートに値を埋め込んで出力する [#rd36ac9d]
#html(<div style="padding-left:10px">)
*** テンプレートとなるPDFの作成 [#n528bd21]
#html(<div style="padding-left:10px">)
別にTCPDFで作らなくても良いが。
print_template.php
#mycode2(){{
<?php
include("./TCPDF/tcpdf.php");
define("MY_PDF_PAGE_ORIENTATION" , "P"); // P:Portrait, L:Landscape
define("MY_PDF_FONT_NAME" , "kozgopromedium"); // kozminproregular
define("MY_PDF_FONT_SIZE" , 10);
define("MY_PDF_UNIT" , "mm");
define("MY_PDF_PAGE_FORMAT" , "A4");
define("MY_PDF_IMAGE_SCALE_RATIO" , 1);
define("MY_PDF_MARGIN_HEADER" , 0);
define("MY_PDF_MARGIN_FOOTER" , 0);
define("MY_PDF_MARGIN_TOP" , 10);
define("MY_PDF_MARGIN_LEFT" , 15);
define("MY_PDF_MARGIN_RIGHT" , 15);
define("MY_PDF_MARGIN_BOTTOM" , 20);
$pdf = new TCPDF(MY_PDF_PAGE_ORIENTATION, MY_PDF_UNIT, MY_PDF_PAGE_FORMAT, true, 'UTF-8', false);
$pdf->SetTitle('PDF 出力テスト');
$pdf->SetMargins(MY_PDF_MARGIN_LEFT, MY_PDF_MARGIN_TOP, MY_PDF_MARGIN_RIGHT);
$pdf->SetAutoPageBreak(TRUE, MY_PDF_MARGIN_BOTTOM);
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(true);
$pdf->setImageScale(MY_PDF_IMAGE_SCALE_RATIO);
$pdf->SetFont(MY_PDF_FONT_NAME, "", 10);
$pdf->AddPage();
$html =<<<_EO_HTML_
<style>
table.tbl {
border-collapse: collapse;
}
table.tbl tr th {
background-color: #efe;
border: 1px solid #333;
padding: 10px; /* 効かない */
}
table.tbl tr td {
border: 1px solid #333;
padding: 10px; /* 効かない */
}
.center {
text-align: center;
}
</style>
<h1>PDF出力テスト</h1>
<table class="tbl" cellpadding="5">
<tr><th>列1</th><th>列2</th><th>列3</th></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
<tr><td></td><td></td><td></td></tr>
</table>
_EO_HTML_;
$pdf->writeHTML($html, true, false, true, false, '');
// ファイルに保存
$fileName = "/tmp/template.pdf";
$pdf->Output($fileName, 'F');
?>
}}
&br;
#myterm2(){{
# 実行
php print_template.php
# 作成したテンプレートをカレントディレクトリにコピー
cp /tmp/template.pdf ./
}}
#html(</div>)
*** 作成したテンプレートに値を埋め込む [#p0b508e3]
#html(<div style="padding-left:10px">)
ここから、実際にPDFテンプレートに値を埋め込むプログラム。
※出力位置の調整が若干面倒。
use_template.php
#mycode2(){{
<?php
use setasign\Fpdi;
include("./TCPDF/tcpdf.php");
include("./FPDI/src/autoload.php");
define("MY_PDF_PAGE_ORIENTATION" , "P"); // P:Portrait, L:Landscape
define("MY_PDF_FONT_NAME" , "kozgopromedium"); // kozminproregular
define("MY_PDF_FONT_SIZE" , 10);
define("MY_PDF_UNIT" , "mm");
define("MY_PDF_PAGE_FORMAT" , "A4");
define("MY_PDF_IMAGE_SCALE_RATIO" , 1);
define("MY_PDF_MARGIN_HEADER" , 0);
define("MY_PDF_MARGIN_FOOTER" , 0);
define("MY_PDF_MARGIN_TOP" , 10);
define("MY_PDF_MARGIN_LEFT" , 15);
define("MY_PDF_MARGIN_RIGHT" , 15);
define("MY_PDF_MARGIN_BOTTOM" , 20);
//class MYPDF extends TCPDF {
class MYPDF extends Fpdi\TcpdfFpdi {
// フッタのカスタマイズ(ページ番号を出力する)
public function Footer() {
$this->SetY(-15); // Position at 15 mm from bottom
$this->SetFont('helvetica', 'I', 8);
$this->Cell(0, 10, 'Page '.$this->getAliasNumPage().'/'.$this->getAliasNbPages(), 0, false, 'C', 0, '', 0, false, 'T', 'M');
}
}
$pdf = new MYPDF(MY_PDF_PAGE_ORIENTATION, MY_PDF_UNIT, MY_PDF_PAGE_FORMAT, true, 'UTF-8', false);
$pdf->SetTitle('PDFテンプレートに値を埋め込むテスト');
$pdf->SetMargins(MY_PDF_MARGIN_LEFT, MY_PDF_MARGIN_TOP, MY_PDF_MARGIN_RIGHT);
$pdf->SetAutoPageBreak(TRUE, MY_PDF_MARGIN_BOTTOM);
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(true);
$pdf->setImageScale(MY_PDF_IMAGE_SCALE_RATIO);
$pdf->SetFont(MY_PDF_FONT_NAME, "", 10);
$pdf->AddPage();
// テンプレート読み込んでページに適用
$pdf->setSourceFile('./template.pdf');
$pdf->useTemplate($pdf->importPage(1));
// 出力位置の調整が少し面倒
function printRow($pdf, $index, $cols){
$y = 31 + $index * 8;
$posX = array(15, 75, 135);
foreach ($cols as $i => $col) {
$x = $posX[$i];
$pdf->SetXY($posX[$i], $y);
$pdf->Write(0, $col);
}
}
for ($i = 0; $i < 10; $i++) {
$no = $i + 1;
printRow($pdf, $i, array("test${no}-1", "test${no}-2", "test${no}-3"));
}
// 作成したPDFをブラウザに表示
$fileName = "use_template.pdf";
$pdf->Output($fileName, 'I');
//$data = $pdf->Output(null,'S'); // PDFデータだけ取得する場合
?>
}}
#html(</div>)
#html(</div>)