FileMakerといえば、帳票だ。持ち前の簡単・便利な操作性を活かしてパパッと帳票が組めるのはおおきな強みとひとつだと言えよう。FileMaker ServerとFileMaker Pro、そしてPHPを組みあわせれば「FileMakerでデザインした帳票をPDF化し、それをWebアプリケーションから自由にダウンロード」といったこともできてしまう。

今回は「FileMakerでデザインしたPDFをWebアプリケーションからダウンロードする」という、とっておきの構築例を紹介しよう。

FileMakerで帳票を設計し、WebからPDFをダウンロード!

第5回の最後にやや自論ではあるが、FileMakerをWebアプリケーションのバックエンドデータベースエンジンとして採用するメリットのひとつに「公開/スタックするデータをエンドユーザがFileMakerをつかって自由に加工ができること」を挙げた。FileMakerを使いこなしてきた方々にはもはや説明不要だろうが、スクリプトステップを使用したデータ加工と直感的なレイアウトを即座にデザインできるユーザインタフェースはFileMakerの得意とする分野だ。

こと「帳票」に関して言えば、持ち前の簡単・便利な操作性と「集計機能」を駆使し、簡単にレイアウトがデザインできるように工夫されている。特別な知識もいらないので「エンドユーザがちょっとレイアウトを変更したくなった」という場合でも、すこしくらいなら対応できてしまう。こころ強い機能のひとつと言えるだろう。

FileMaker Pro 8からはPDF形式でのエクスポートがサポートされ、FileMakerのレイアウトをそのままPDFに出力することが可能となった。スクリプトステップ中にも呼びだすことが可能なので、一括処理で各レコードのPDFを生成、といったこともできる。残念ながらこの「レコードを PDF として保存」スクリプトステップはサーバスケジュール/Web公開からのスクリプト起動には対応していないため、Webアプリケーション上からシームレスにPDF出力とまではできないが、それに近いところまでは実装可能だ。前置きが長くなってしまったが、さっそく実装をしてみよう。

Webアプリケーション上からレコードを登録し、PDFを生成しダウンロードするまでのながれは次のとおり。

  1. Webブラウザ上でデータを登録 (第4回のfm_list.php, fm_new.phpほかを一部流用)
  2. FileMaker ProでFileMaker Server上にて公開されているファイルを開き「レコードを PDF として保存」をふくむFileMakerスクリプトを実行。PDFをWebサーバのドキュメントパス以下に保存し、ファイル名をレコードに保存する。
  3. Webブラウザ上でレコードに保存されているファイル名を元に出力されたPDFへアクセス。

2のドキュメントパスについては、Windows+IISの場合は「C:\Inetpub\wwwroot\」、Mac OS X+Apacheの場合は「/Library/WebServer/Documents/」といった具合だ。今回はMacOSのホームディレクトリのSites以下に保存する。ネットワーク上の他のマシンにPDFを置きたい場合は、FileMakerスクリプト上で出力パスの表記をネットワークパス(filewin://)に合わせればOKだ。

fm_new.php - 第4回と同一のため、省略

fm_list.php - pdfフィールドが空欄でない場合は、PDFファイルへのリンクを表示するように

<?php

include_once('./fx/FX.php');
include_once('./fx/server_data.php');

// 文字列エスケープ用関数
function h($string)
{
    return htmlspecialchars(trim($string), ENT_QUOTES, 'UTF-8');
}

$data = new FX($serverIP, $webCompanionPort, $dataSourceType, $scheme);
$data->SetDBData($databaseFileName,'web_list', 5);
$data->SetDBUserPass($webUN,$webPW);
$data->SetCharacterEncoding('utf8');
$data->SetDataParamsEncoding('utf8');

$data->AddSortParam('f_serial', 'descend');
$data->FMSkipRecords($_GET['skip']);

$dataSet = $data->FMFind();

?>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>FX.php データ一覧</title>
</head>

<body>

    <p>
        該当: <?php echo number_format($dataSet['foundCount']); ?>件、
        <?php echo h(number_format($_GET['skip']+1)); ?>件目から <?php echo h($_GET['skip']+count($dataSet['data']) )?>件目を表示中
    </p>

    <table border="1">
        <thead>
            <tr>
                <th>
                    シリアル
                </th>
                <th>
                    氏名
                </th>
                <th>
                    FileMakerの<br>Webはいつから
                </th>
                <th>
                    使用したことがある<br>バージョン
                </th>
                <th>
                    PDF
                </th>
            </tr>
        </thead>
        <tbody>
        <?php
        foreach ( $dataSet['data'] as $key => $value )
        {
        ?>
            <tr>
                <td>
                    <?php
                    echo h($value['f_serial'][0]);
                    ?>
                </td>
                <td>
                    <?php
                    echo h($value['f_name'][0]);
                    ?>
                </td>
                <td>
                    <?php
                    echo h($value['f_history'][0]);
                    ?>
                </td>
                <td>
                    <?php
                    echo h(str_replace("\n", ', ', $value['f_useVersion'][0]));
                    ?>
                </td>
                <td align="center">
                    <?php
                    if ('' !== $value['f_pdfFile'][0])
                    {
                        echo '<a href="./pdf/' . h($value['f_pdfFile'][0]) . '">[PDF]</a>';
                    }
                    else
                    {
                        echo '-';
                    }
                    ?>
                </td>
            </tr>
        <?php
        }
        ?>
        </tbody>
    </table>

    <p>
        <?php 
        if (!empty($dataSet['linkPrevious']))
        {
            ?>
            <a href="<?php echo h($dataSet['linkPrevious']); ?>">前のページへ</a>
            <?php
        }
        else
        {
            ?>
            前のページへ
            <?php
        }
        ?>
        / 
        <?php 
        if (!empty($dataSet['linkNext']))
        {
            ?>
            <a href="<?php echo h($dataSet['linkNext']); ?>">次のページへ</a>
            <?php
        }
        else
        {
            ?>
            次のページへ
            <?php
        }
        ?>
    </p>

</body>

</html>

recordsToPDF - f_pdfOutFlgが0のレコードすべてにPDFを作成するFileMakerスクリプト

# 対象レコードのひとつひとつにPDFを作成
変数を設定 [ $filePath; 値:"filemac:/Macintosh HD/Users/hiroaki/Sites/pdf/" ]
エラー処理 [ オン ]
レイアウト切り替え [ 「pdf_test」 ]
検索モードに切り替え [ ]
フィールド設定 [ fxphp::f_pdfOutFlg; 0 ]
検索実行 [ ]
レコードのソート [ 特定のソート順: fxphp::f_serial; 昇順 ] [ 記憶する; ダイアログなし ]
レコード/検索条件/ページへ移動 [ 最初の ]
Loop
    変数を設定 [ $fileName; 値:"" ]
    変数を設定 [ $outPDFPath; 値:"" ]
    変数を設定 [ $fileName; 値:Year ( Get ( 日付 ) ) & Month ( Get ( 日付 ) ) & Day ( Get ( 日付 ) ) & Hour ( Get ( 時刻 ) ) & Minute ( Get ( 時刻 ) ) & Seconds ( Get ( 時刻 ) ) & "_" & fxphp::f_serial & ".pdf" ]
    変数を設定 [ $outPDFPath; 値:$filePath & $fileName ]
    レコードを PDF として保存 [ ファイル名: 「$outPDFPath」; 現在のレコード ] [ ドキュメント - Compatibility: Acrobat 5 以降 ] [ ページ - 開始ページ: 1; 内容: すべてのページ ] [ セキュリティ - 印刷: 高解像度; 編集: ページの抽出を除くすべて; コピーの有効化; 画面読み上げプログラムの有効化 ] [ 初期表示形式 - 表示: ページパネルとページ; ページレイアウト: 単一ページ; 拡大率: 100% ] [ 記憶する; ダイアログなし ]
    If [ Get ( 最終エラー ) = 0 ]
        フィールド設定 [ fxphp::f_pdfFile; $fileName ]
        フィールド設定 [ fxphp::f_pdfOutFlg; 1 ]
        レコード/検索条件確定 [ ダイアログなし ]
    End If
    レコード/検索条件/ページへ移動 [ 次の; 最後まできたら終了 ]
End Loop

レコード作成時の自動入力オプションで、初期値として0が入るフラグ用フィールドを作成。フラグ値が0ならば「PDFが出力されていない」、フラグ値が1ならば「PDFが出力されている」という定義をしておき、FileMakerスクリプトではつねにフラグ値が0のレコードのみを対象にしていることがポイントだ。

PDF出力用に今回あたらしく追加したフィールド定義

それでは順を追って実行してみよう。

  1. Webブラウザ上でデータを登録 - Webブラウザでfm_new.phpにアクセス

    fm_new.phpにアクセスし、データを入力してFileMakerに保存する

    入力した内容がFileMakerに保存された。この時点ではまだPDFは作成されていない

  2. FileMaker ProでFileMaker Server上にて公開されているファイルを開き「レコードを PDF として保存」をふくむスクリプトを実行 - FileMaker Proで「recordsToPDF」スクリプトを実行

    FileMaker Pro上で「recordsToPDF」を実行。PDFが作成され、f_pdfOutFlgが1に、f_pdfFileにファイル名が格納された

  3. Webブラウザ上でレコードに保存されているパス/ファイル名を元に出力されたPDFへアクセス - fm_list.phpにアクセス

    再度fm_list.phpにアクセス。PDFファイルへのリンクが表示される

    リンクをクリックし、PDFの内容が表示された

PDFが無事にWebブラウザをとおして表示できた。

いまのところFileMaker Serverのスケジュールから実行するFileMakerスクリプトではPDFの出力がサポートされていないため、Webアプリケーション側でレコードを作成した瞬間にPDFを作成する、といった完全な自動化はむずかしい。しかしユーザが手動でFileMakerスクリプトを実行したり、バッチ処理でFileMaker Proクライアントを起動して共有ファイルをオープン、そしてFileMakerスクリプトを実行といった作業ができるとすれば、この手のPDF生成はさまざまなシーンで応用が効くことになる。じつに便利だ。

今回はPDFの出力という、すぐに現場でも実践できるような例を紹介した。通常PDFをWebアプリケーションのみで実装する場合かなり骨の折れる作業となるが、この手法を採用すればPDFを簡単に作成できるだけではなく、突然のレイアウト変更といった場合にも柔軟に対応できるようになってくる。また、もちろんPDF以外にもCSVといったデータもレコードにひもづけることが可能だ。FileMakerをベースにしたWebアプリケーションを組む場合は、FileMakerならではの機能を活かせる設計をしていこう。