PDFlib

高度なPDFアプリケーションの開発を支援する定番プログラムライブラリー Supported by インフォテック株式会社

PDFlib+PDI デモプログラム解説

ここでは、PDFlib デモプログラムで取り上げた PDFlib+PDI のデモプログラムのソースコードと解説を公開しています。

ソースコードのダウンロードはこちらから(zip ファイル)

pdi_demo.php

Word 等で作成した PDF のページをベースとして、必要なテキストやイメージのみを重ねて見積書を作成します。

入力フォームの文字コードは UTF-8 とし、以下のソースコードも同じく UTF-8 で保存されるものとします。また、MS ゴシックと MS 明朝のフォントファイルがソースコードと同じ階層の resource/fonts ディレクトリにあるものとします。これらのフォントをお持ちでない場合、IPA フォントのような再配布可能なフォントファイルをご用意いただき、ソースコードを書き換えてお試しください。

PDF へフォントを埋め込むことはフォントファイルの再配布に近いため、利用規約等で PDF への埋め込みを禁止している場合があります。フォントファイルの利用条件をご確認の上、ご利用ください。

下記のソースコードは PHP 5.4 および PDFlib 9.1 での動作を想定しています。


<?php
// 見積書に記載する情報を $_POST から取得
$estimate_date = $_POST["estimate_date"];
$org_name = $_POST["org_name"];
$stamp_image = $_POST["stamp_image"];
$total_2 = $_POST["total_2"];
$items = Array();
for($i = 1; $i <= 8; $i++) {
  array_push(
    $items,
    Array(
      "item" => $_POST["item_" . $i],
      "count" => $_POST["count_" . $i],
      "price" => $_POST["price_" . $i],
      "amount" => $_POST["amount_" . $i]));
}
$total_1 = $_POST["total_1"];
$memo = $_POST["memo"];

// インポート用の PDF ファイル名を指定
$import_pdf = "pdi_quote.pdf";

/* その他の変数を定義
 * ライセンスキーは PDFlib ライセンス規約により、公開ディレクトリに置いては
 * いけません。外部からアクセスできないディレクトリに設置してください。
 * フォントファイルについても、利用規約等により配布が禁止されている場合が
 * あります。使用するフォントの利用条件をご確認ください。
 */
$licensefile = "/var/pdflib/pdflib_license.txt";
$base_dir = dirname($_SERVER["SCRIPT_FILENAME"]);
$font_dir = $base_dir . "/resource/fonts";
$image_dir = $base_dir . "/images";
$template_dir = $base_dir . "/templates";
$output_pdf = "pdi_demo.pdf";

try {
  // PDFlib オブジェクトの生成
  $pdf = new PDFlib();

  /* PDFlib のパラメータの設定
   * ライセンスキーを記入したライセンスファイルを licensefile で指定することで
   * PDFlib を製品版としてお使いいただけるようになります。(フォーマットについ
   * てはインストールディレクトリの licenses.txt をご覧ください)
   *
   * errorpolicy は、PDFlib の関数でエラーが起きた場合の動作を指定します。
   * return では戻り値としてエラーを知らせ、exception では例外を発生させます。
   * なお、デフォルトの legacy は非推奨です。
   *
   * SearchPath は、PDF で使用するファイルを読み込む際の、検索対象にする
   * ディレクトリを指定します。
   *
   * stringformat は PDFlib に渡す文字列のエンコードを指定します。
   */
  if(file_exists($licensefile))
    $pdf->set_option("licensefile=$licensefile");
  $pdf->set_option("errorpolicy=return");
  $pdf->set_option("SearchPath=$font_dir");
  $pdf->set_option("SearchPath=$image_dir");
  $pdf->set_option("SearchPath=$template_dir");
  $pdf->set_option("stringformat=utf8");

  /* 文書情報の設定
   *  文書のプロパティの概要に表示されるタイトルと作成者を指定します。
   *  その他サブタイトル、キーワード、作成日、更新日、アプリケーション等の規定
   *  のプロパティやカスタムプロパティを指定できます。
   */
  $pdf->set_info("Title", "PDFlib+PDI デモプログラム (見積書作成)");
  $pdf->set_info("Author", "infoTek K.K.");

  /* 文書の作成
   *  PDF 文書の作成を開始します。begin_document() の第一引数が空文字の場合、
   *  PDF はメモリ上に作成され、end_document() 後に get_buffer() で取得するこ
   *  とができます。
   */
  $pdf->begin_document("", "");

  /* フォントのロード
   *  ページ上のテキストを出力する際に使用するフォントファイルを読み込みます。
   *  FontOutline でフォントファイル内のフォント名を指定し、load_font() で該当
   *  のフォントを使えるようにします。
   *  FontOutline では任意の名前をつけることもできますが、フォントが TrueType
   *  コレクション (.ttc) の場合は、フォント名での指定をお薦めします。
   *  フォントの読み込みに失敗した場合、エラーコード (PHP では 0) が返ります。
   *  成功した場合はフォントハンドルが得られます。
   */
  $pdf->set_option("FontOutline={MS-Gothic=msgothic.ttc}");
  $ms_gothic = $pdf->load_font("MS-Gothic", "unicode", "embedding");
  if($ms_gothic == 0) {
    // フォントのロードに失敗
    throw new PDFlibException();
  }
  $pdf->set_option("FontOutline={MS-Mincho=msmincho.ttc}");
  $ms_mincho = $pdf->load_font("MS-Mincho", "unicode", "embedding");
  if($ms_mincho == 0) {
    // フォントのロードに失敗
    throw new PDFlibException();
  }

  /* ページの作成
   *  ページを作成します。
   *  本サンプルでは取り出したページの上に重ねるので、ページサイズを入力せずに
   *  作ります。
   */
  $pdf->begin_page_ext(0, 0, "");

  /* PDF をインポートしてページに配置
   *  既存の PDF から1ページ目を取り出し、現在のページに貼り付けます。
   *  adjustpage キーワードにより、ページサイズは貼り付けたページのサイズと
   *  同じになります。
   */
  $pdi = $pdf->open_pdi_document($import_pdf, "");
  if($pdi == 0) {
    // PDF のオープンに失敗
    throw new PDFlibException();
  }
  $pdi_page = $pdf->open_pdi_page($pdi, 1, "");
  if($pdi_page == 0) {
    // ページのオープンに失敗
    throw new PDFlibException();
  }
  $pdf->fit_pdi_page($pdi_page, 0, 0, "adjustpage");

  /* 1行テキストの配置
   *  ページ上にテキストを配置します。
   *  POST された文字列を、取り込んだページ上に配置していきます。
   *  boxsize で幅と高さを指定すると、テキストは fitmethod に従って配置されま
   *  す。
   */
  $optlist = "font=$ms_mincho fontsize=10.5";
  $text = "見積作成日:$estimate_date";
  $pdf->fit_textline($text, 370, 680, $optlist);
  $optlist = "font=$ms_gothic fontsize=18 boxsize={300 18} fitmethod=meet" .
             " underline=true fontstyle=bold";
  $text = $org_name;
  $pdf->fit_textline($text, 86, 645, $optlist);
  $optlist = "font=$ms_gothic fontsize=15 underline=true fontstyle=bold" .
             " boxsize={300 0} position={center}";
  $text = "合計金額:$total_2";
  $pdf->fit_textline($text, 150, 470, $optlist);

  $y = 393;
  $optlist_base = "font=$ms_gothic fontsize=10.5";
  $item_x = 95;
  $item_optlist = $optlist_base . " boxsize={205 10.5} position={left center}";
  $count_x = 305;
  $count_optlist = $optlist_base . " boxsize={53 10.5} position={right center}";
  $price_x = 365;
  $price_optlist = $optlist_base . " boxsize={67 10.5} position={right center}";
  $amount_x = 440;
  $amount_optlist = $optlist_base . " boxsize={73 10.5} position={right center}";
  for($i = 0; $i < count($items); $i++) {
    $text = $items[$i]["item"];
    if($text == "")
      break;
    $pdf->fit_textline($text, $item_x, $y, $item_optlist);
    $text = $items[$i]["count"];
    $pdf->fit_textline($text, $count_x, $y, $count_optlist);
    $text = $items[$i]["price"];
    $pdf->fit_textline($text, $price_x, $y, $price_optlist);
    $text = $items[$i]["amount"];
    $pdf->fit_textline($text, $amount_x, $y, $amount_optlist);
    $y -= 18.5;
  }
  if($i > 1) {
    $text = "小計";
    $pdf->fit_textline($text, $item_x, $y, $item_optlist);
    $text = $_POST["subtotal"];
    $pdf->fit_textline($text, $amount_x, $y, $amount_optlist);
    $y -= 18.5;
  }

  if($i > 0) {
    $text = "消費税";
    $pdf->fit_textline($text, $item_x, $y, $item_optlist);
    $text = $_POST["tax"];
    $pdf->fit_textline($text, $amount_x, $y, $amount_optlist);
    $y -= 18.5;
  }

  $text = $total_1;
  $optlist = "font=$ms_gothic fontsize=10.5 boxsize={73 0} position={right center}";
  $pdf->fit_textline($text, 440, 214, $optlist);

  /* イメージの配置
   *  ページ上にイメージを配置します。
   *  イメージは load_image() で取り込み使える状態にし、close_image() で
   *  開放します。
   *  イメージの配置は fit_image() を使い、load_image() から返された
   *  イメージハンドルでイメージを指定します。
   */
  if($stamp_image == 1) {
    $optlist = "";
    $image = $pdf->load_image("gif", "stamp.gif", $optlist);
    if($image == 0) {
      // イメージのロードに失敗
      throw new PDFlibException();
    }
    $optlist = "";
    $pdf->fit_image($image, 460, 555, $optlist);
    $pdf->close_image($image);
  }

  /* 複数行テキストの配置
   *  複数行に渡るテキストを配置します。
   *  add_textflow() で作られた矩形領域にテキストを流し込みます。今回は使用し
   *  ていませんが、fit_textflow() の戻り値によりテキストを配置した結果 (全て
   *  配置した、領域いっぱいに配置しまだテキストが残っている、テキストが領域に
   *  まったく入らない 等) を返します。
   */
  $optlist = "font=$ms_mincho fontsize=10.5";
  $text = $memo;
  $tf = $pdf->add_textflow(0, $text, $optlist);
  if($tf == 0) {
    // テキストフロー作成に失敗
    throw new PDFlibException();
  }
  $optlist = "";
  $pdf->fit_textflow($tf, 95, 200, 510, 115, $optlist);
  $pdf->delete_textflow($tf);

  // インポートしたページと PDF を閉じる
  $pdf->close_pdi_page($pdi_page);
  $pdf->close_pdi_document($pdi);

  /* ページを閉じる
   *  ページ上への出力が終わったらページを閉じます。
   *  もし複数ページに渡る PDF を作成する場合、再度 open_page_ext() でページを
   *  開きます。
   */
  $pdf->end_page_ext("");

  /* 文書を閉じる
   *  ページ全体の出力が終わったら、ドキュメントを閉じます。
   *  ドキュメントを閉じると、PDF が作成されます。
   */
  $pdf->end_document("");

  /* PDF をブラウザに出力
   *  get_buffer() で作成した PDF を受け取り、ヘッダーと共に送信します。
   */
  $buf = $pdf->get_buffer();
  $len = strlen($buf);

  header("Content-type: application/pdf");
  header("Content-Length: $len");
  header("Content-Disposition: inline; filename=$output_pdf");

  print($buf);
}
catch(PDFlibException $e) {
  /* PDFlib で発生した例外の処理
   *  PDFlib で例外が発生した場合、PDFlibException クラスが送出されます。
   *  PDFlibException クラスでは、最後に実行された PDFlib の API 名、
   *  エラーコード、エラーの詳細を取得できます。
   */
  echo($e->get_apiname() . "[" . $e->get_errnum() . "]: " . $e->get_errmsg());
}
catch(Exception $e) {
  echo($e);
}

// PDFlib オブジェクトの解放
if(isset($pdf)) {
  $pdf->delete();
}
					
PHP 5 / PDFlib 9

本サンプルプログラムのソースコードは、弊社から購入した PDFlib 関連製品を利用する目的に限り、無償で利用、改変、複写することができます。

(Jan 30, 2018 - Sep 28, 2018)