set_option("searchpath={" . $searchpath . "}"); /* load_font() 等でエラーが起きた場合、戻り値をチェックする */ $p->set_option("errorpolicy=return"); $p->set_option("stringformat=utf8"); if ($p->begin_document($outfile, "") == 0) throw new Exception("Error: " . $p->get_errmsg()); $p->set_info("Creator", "PDFlib Cookbook"); $p->set_info("Title", $title ); /* インポートしたPDFドキュメントを開く */ $stationery = $p->open_pdi_document($infile, ""); if ($stationery == 0) throw new Exception("Error: " . $p->get_errmsg()); /* インポートしたPDFの1ページ目を開く */ $page = $p->open_pdi_page($stationery, 1, ""); if ($page == 0) throw new Exception("Error: " . $p->get_errmsg()); /* ボールドとレギュラースタイルのフォントをロードする */ $boldfont = $p->load_font("Helvetica-Bold", "unicode", ""); if ($boldfont == 0) throw new Exception("Error: " . $p->get_errmsg()); $regularfont = $p->load_font("Helvetica", "unicode", ""); if ($regularfont == 0) throw new Exception("Error: " . $p->get_errmsg()); /* 出力ページを始める */ $p->begin_page_ext($pagewidth, $pageheight, ""); /* インポートしたPDFページを配置してクローズする */ $p->fit_pdi_page($page, 0, 0, ""); $p->close_pdi_page($page); /* 顧客のアドレスを出力する */ $y = $ystart; $p->setfont($regularfont, $fontsize); for ($i = 0; $i < count($address); $i++) { $p->fit_textline($address[$i], $llx, $y, ""); $y -= $yoffset; } /* ヘッダーと日付を出力する */ $y -= 3 * $yoffset; $p->setfont($boldfont, $fontsize); $p->fit_textline("INVOICE", $llx, $y, "position {left top}"); $p->fit_textline($fulldate, $urx, $y, "position {right top}"); $y -= 3 * $yoffset; /* ---------------------------------------------------- * ヘッダーセルを含む最初のテーブル行を追加する * ---------------------------------------------------- */ /* テーブルヘッダーのテキスト行セルを追加するための、一般的なオプション * リストを準備する。行の高さとテキストの位置を指定する。 * テキストはそれぞれ右上か左上に配置される。 * * テキストラインとテキストフローの縦方向の位置については下記に注意する。 * 大文字の高さは、フォントのキャップハイトの値で正確に表される。 * そのため、キャップハイト値を使用してフォントサイズを指定する。 * 例えば、キャップハイトを8.5にするとフォントサイズは約12ポイントとなり、 * マージン4も加えると、行全体の高さが16ポイントになる */ $head_opts_right = "fittextline={position={right top} " . " font=" . $boldfont . " fontsize={capheight=" . $capheight . "}} " . " rowheight=" . $rowheight . " margin=" . $margin; $head_opts_left = "fittextline={position={left top} " . " font=" . $boldfont . " fontsize={capheight=" . $capheight . "}} " . " rowheight=" . $rowheight . " margin=" . $margin; $col = 1; $row = 1; /* 上記で定義したオプションリストを使用して、各ヘッダーセルを追加する。 * さらに列幅を指定する。 */ $tbl = $p->add_table_cell($tbl, $col++, $row, "ITEM", $head_opts_right . " colwidth=" . $c1); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); $tbl = $p->add_table_cell($tbl, $col++, $row, "DESCRIPTION", $head_opts_left . " colwidth=" . $c1); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); $tbl = $p->add_table_cell($tbl, $col++, $row, "QUANTITY", $head_opts_right . " colwidth=" . $c3); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); $tbl = $p->add_table_cell($tbl, $col++, $row, "PRICE", $head_opts_right . " colwidth=" . $c4); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); $tbl = $p->add_table_cell($tbl, $col++, $row, "SUM", $head_opts_right . " colwidth=" . $c5); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); $row++; /* ------------------------------------------- * 後続のテーブル行にボディセルを追加する * ------------------------------------------- */ /* テーブル本体に、テキスト行を追加するための一般的なオプションリストを指定する。 * ヘッダーセル用に定義したオプションリストと似ているが、 * ここでは、フォントはレギュラーフォントを使用する。 */ $body_opts = "fittextline={position={right top} " . " font=" . $regularfont . " fontsize={capheight=" . $capheight . "}} " . " rowheight=" . $rowheight . " margin=" . $margin; for ($itemno = 1; $itemno <= count($items); $itemno++, $row++) { $col = 1; /* --------------------------------------------------------------- * 1番目の列(ITEM)にテキストラインセルを、上記のボディセルで * 定義したオプションと共に追加する。 * --------------------------------------------------------------- */ $tbl = $p->add_table_cell($tbl, $col++, $row, $itemno, $body_opts); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); /* -------------------------------------------------------------- * 2番目の列(DESCRIPTION)にテキストフローセルを追加する * -------------------------------------------------------------- */ /* テキストフローを追加するためのオプションリストを準備する。 * * テキストラインとテキストフローの縦方向の位置については下記に注意する。 * 大文字の高さは、フォントのキャップハイトの値で正確に表される。 * そのため、キャップハイト値を使用してフォントサイズを指定する。 * 例えば、キャップハイトを8.5にするとフォントサイズは約12ポイントとなり * マージン4も加えると、行全体の高さが16ポイントになる。 */ $tf_opts = "font=" . $regularfont . " fontsize={capheight=" . $capheight . "} leading=" . $leading; /* テキストフローセルを追加するためのオプションリストを準備する * * テキストフローの1行目はテキストラインのベースラインに揃える。 * 同時に、テキストラインはセルの上部の境界線から、テキストフローと * 同じ距離にある必要がある。 * 上端に余白を生じさせないために、テキストフローセルを追加する際に * fittextflow={firstlinedist=capheight} を使用する。そしてテキスト * ラインと同じく、マージン4ポイントを追加する */ $bodytf_opts = "fittextflow={firstlinedist=capheight}" . " colwidth=" . $c2 . " margin=" . $margin; /* 上記で定義したオプションを使用してテキストフローを追加する */ $tf = $p->add_textflow(0, $items[$itemno-1][0], $tf_opts); if ($tf == 0) throw new Exception("Error: " . $p->get_errmsg()); /* 上記で定義したオプションを使用してテーブルセルを追加する */ $tbl = $p->add_table_cell($tbl, $col++, $row, "", $bodytf_opts . " textflow=" . $tf); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); $tf = 0; /* ----------------------------------------------------------- * 3番目の列(Quantity)にテキストラインセルを、上記のボディセルで * 定義したオプションと共に追加する。 * ----------------------------------------------------------- */ $tbl = $p->add_table_cell($tbl, $col++, $row, $items[$itemno-1][1], $body_opts); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); /* ----------------------------------------------------------- * 4番目の列(Price)にテキストラインセルを、上記のボディセルで * 定義したオプションと共に追加する。 * ----------------------------------------------------------- */ $tbl = $p->add_table_cell($tbl, $col++, $row, $items[$itemno-1][2], $body_opts); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); /* --------------------------------------------------------------- * 5番目の列(SUM)にテキストラインセルを、上記のボディセルで定義 * したオプションと共に追加する。 * 小数点以下を2桁でフォーマットする。 * --------------------------------------------------------------- */ $sum = $items[$itemno-1][1] * $items[$itemno-1][2]; $roundedValue = sprintf("%.2f", $sum); $tbl = $p->add_table_cell($tbl, $col, $row, $roundedValue, $body_opts); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); /* 総計を計算する */ $total += $sum; } /* for */ /* マッチボックスと呼ばれる空のフッター(subtotal)を追加する。 * ここに小計または総計を追加する。 * マッチボックス2つの列(4列目、5列目)にまたがっている。 */ $footer_opts = "rowheight=" . $rowheight . " colspan=2 margin =" . $margin . " matchbox={name=subtotal}"; $tbl = $p->add_table_cell($tbl, $maxcol-1, $row, "", $footer_opts . ""); if ($tbl == 0) throw new Exception("Error adding cell: " . $p->get_errmsg()); /* ------------------------------------ * テーブルを複数のページに配置する * ------------------------------------ */ /* 全てのテーブルが配置されるまで繰り返す。 * 配置するテーブルインスタンスの分だけ、新しいページを作成する。 */ do { /* 最初の行はヘッダー行で新しいページ毎に繰り返される。 * 最後の行はフッター行で同様に新しいページごとに繰り返される。 * ヘッダー行は水色で塗りつぶし、フッター行はオレンジで塗りつぶす。 * 奇数行はグレーで塗りつぶす。 */ $fit_opts = "header=" . $nheaders . " footer=" . $nfooters . " fill={{area=rowodd fillcolor={gray 0.9}} " . "{area=header fillcolor={rgb 0.90 0.90 0.98}} " . "{area=footer fillcolor={rgb 0.98 0.92 0.84}}}"; /* テーブルインスタンスを配置する */ $result = $p->fit_table($tbl, $llx, $lly, $urx, $y, $fit_opts); /* エラーが発生したか、もしくはテーブルのフィットボックスが小さすぎて * コンテンツが入りきらない場合 */ if ($result == "_error") throw new Exception ("Couldn't place table : " . $p->get_errmsg()); /* もし全ての行が配置されている場合はフッター行に定義されている * マッチボックスに合計を出力する。マッチボックスをfit_textline()に * 直接定義することはできないため、マッチボックスの座標を取得し * テキストを合わせる。 */ if ($result != "_boxfull") { /* 総計(total)を小数点以下を2桁でフォーマットする */ $roundedValue = sprintf("%.2f", $total); $contents = "total: " . $roundedValue; /* 「subtotal」マッチボックスの3番目の(右上)の角の座標を取得する。 * パラメータ 1 はマッチボックスの最初のインスタンスを示している。 */ $x3 = 0; $y3 = 0; if ($p->info_matchbox("subtotal", 1, "exists") == 1) { $x3 = $p->info_matchbox("subtotal", 1, "x3"); $y3 = $p->info_matchbox("subtotal", 1, "y3"); } else { throw new Exception("Error: " . $p->get_errmsg()); } /* 取得したコーナー座標 (x3, y3)になマージン幅を加え * テキスト行を開始する。テキストは右揃えにする。 */ $p->setfont($boldfont, $fontsize); $p->fit_textline($contents, $x3 - $margin, $y3 - $margin, "position={right top}"); } /* 次のページに残りの行を配置する前に、最後のテーブル列の下にある * 現在のページのテーブルインスタンスの全ての行の小計を出力する。 */ else if ($result == "_boxfull") { /* テーブルインスタンスの最後の本文行の行数を取得する */ $lastrow = $p->info_table($tbl, "lastbodyrow"); /* 小計を計算する */ $subtotal = 0; for ($i = 0 ; $i < $lastrow - $nfooters; $i++) { $subtotal += $items[$i][1] * $items[$i][2]; } /* フッター行に定義されたマッチボックスに小計を出力する。 * マッチボックスは直接参照することができないため、マッチボックスの * 座標を取得し、テキストを合わせる。 */ /*小計(subtotal)を小数点以下を2桁でフォーマットする */ $roundedValue = sprintf("%.2f", $subtotal); $contents = "subtotal: " . $roundedValue; /* 「subtotal」マッチボックスの3番目の(右上)の角の座標を取得する。 * パラメータの 1 はマッチボックスの最初のインスタンスを示している。 */ $x3 = 0; $y3 = 0; if ($p->info_matchbox("subtotal", 1, "exists") == 1) { $x3 = $p->info_matchbox("subtotal", 1, "x3"); $y3 = $p->info_matchbox("subtotal", 1, "y3"); } else { throw new Exception("Error: " . $p->get_errmsg()); } /* 取得したコーナー座標 (x3, y3)にマージン幅を加え * テキスト行を開始する。テキストは右揃えにする。 */ $p->setfont($boldfont, $fontsize); $p->fit_textline($contents, $x3 - $margin, $y3 - $margin, "position={right top}"); /* 「Continued」を出力する */ $p->setfont($regularfont, $fontsize); $p->fit_textline("-- Continued --", $urx, $ycontinued, "position {right top}"); $p->end_page_ext(""); $p->begin_page_ext($pagewidth, $pageheight, ""); $y = $ystart; } } while ($result == "_boxfull"); /* ----------------------------------------------- * テーブルの後にテキストを配置する * ----------------------------------------------- */ /* 現在のテーブルインスタンスのテーブルの高さを取得する */ $tabheight = $p->info_table($tbl, "height"); $y = $y - (int) $tabheight - $yoffset; /* テーブルの後に配置するテキストフローを追加する */ $tf_opts = "font=" . $regularfont . " fontsize=" . $fontsize . " leading=" . $leading . " alignment=justify"; $tf = $p->add_textflow(0, $closingtext, $tf_opts); if ($tf == 0) throw new Exception("Error: " . $p->get_errmsg()); /* 全てのテキストを配置し、fit_textflow()の戻り値が「_stop」に * なるまでループする */ do { /* テキストフローを配置する */ $result = $p->fit_textflow($tf, $llx, $lly, $urx, $y, ""); if ($result == "_error") throw new Exception ("Couldn't place table : " . $p->get_errmsg()); if ($result == "_boxfull" || $result == "_boxempty") { $p->setfont($regularfont, $fontsize); $p->fit_textline("-- Continued --", $urx, $ycontinued, "position {right top}"); $p->end_page_ext(""); $p->begin_page_ext($pagewidth, $pageheight, ""); $y = $ystart; } } while (!$result == "_stop"); $p->end_page_ext(""); $p->end_document(""); $p->close_pdi_document($stationery); $buf = $p->get_buffer(); $len = strlen($buf); header("Content-type: application/pdf"); header("Content-Length: $len"); header("Content-Disposition: inline; filename=table_invoice.pdf"); print $buf; } catch (PDFlibException $e){ echo("PDFlib exception occurred:\n" . "[" . $e->get_errnum() . "] " . $e->get_apiname() . ": " . $e->get_errmsg() . "\n"); exit(1); } catch (Exception $e) { echo($e->getMessage()); exit(1); } $p = 0; ?>