技術記事

DelphiからExcelワークブックをPDF/Aへエクスポートする

HotXLSはExcel不要、PDFプリンタドライバ不要で、DelphiおよびC++Builderからワークブックまたは単一ワークシートを直接PDF/Aへエクスポートする。TXLSPDFExport上でUsePDFAを設定しプロファイルを選ぶと、エクスポートされたファイルは出力インテントとして埋め込まれたsRGB ICCプロファイル、XMPメタデータ内のpdfaid識別ブロック、適合レベルに応じたPDFバージョンヘッダーを持つ

この要件は多くの場合、開発者からではなく記録保存ポリシーから来る。財務諸表、検査結果、規制当局への提出書類、そして公的機関が数十年にわたり保管しなければならないものは、50年後にも同じように表示されるフォーマットで保存する必要があり、それを保証するために存在するのがPDF/A、すなわちISO 19005である。スプレッドシートは生きた計算であるが、スプレッドシートのアーカイブコピーはその固定された一葉の写しでなければならない

何がPDFをアーカイブ用PDFたらしめるのか

3つの要件がほとんどの仕事をこなす。ファイルは自己完結でなければならず、使用するすべてのフォントが埋め込まれ、外部リソースが参照されないこと。色は曖昧さがあってはならず、これはファイルが準備された色空間を示す出力インテントを意味する。そして、パート番号と適合レベルを宣言するXMPメタデータを通じて、自身を識別できなければならない

HotXLSはこの3つすべてを提供する。sRGBプロファイルは3成分とDeviceRGBを代替色空間とするストリームオブジェクトとして埋め込まれ、条件と識別子の両方がsRGB IEC61966-2.1を示すGTS_PDFA1出力インテントから参照される。XMPパケットはpdfaidのパートと適合エントリを保持する。プロファイルのバイト列は実行時にロードされるのではなくライブラリにコンパイル済みで組み込まれているため、デプロイの手順は不要であり、ファイルの欠落によってアーカイブ用エクスポートが通常のエクスポートに成り下がる心配もない

3 つの PDF/A アーカイブ要件と、Delphi から HotXLS が書く装備の図。埋め込み FontFile2 サブセット、GTS_PDFA1 sRGB 出力インテント、pdfaid XMP 識別
PDF/A ファイルは自己完結し、色が曖昧でなく、自己識別できなければなりません。HotXLS は UsePDFA プロパティのペアから、それに応える仕組みを書き出します
uses
  lxHandleX, lxPDF;

var
  Book: TXLSXWorkbook;
  Exporter: TXLSPDFExport;
begin
  Book := TXLSXWorkbook.Create;
  Exporter := TXLSPDFExport.Create;
  try
    if Book.Open('quarterly-results.xlsx') <> 1 then
      Exit;

    Exporter.UsePDFA := True;
    Exporter.PDFAProfile := xlsPdfA2b;      // ISO 19005-2 level B
    Exporter.DocumentLanguage := 'en-GB';
    Exporter.TagMode := xlsPdfTagsAutomatic;

    if Exporter.SaveAsPDF(Book, 'quarterly-results-archive.pdf') <> 1 then
      raise Exception.Create('archival export failed');
  finally
    Exporter.Free;
    Book.Free;
  end;
end;

どのプロファイルを選ぶべきか

プロファイルの列挙はPDF/A-1、PDF/A-2、PDF/A-3をカバーし、それぞれにアクセシブル版とベーシック版がある。実用上の違いは、この一覧から想像されるより小さい

ベーシック版であるレベルBは、見た目の表示が再現可能であることを保証する。レベルAはそれに加えて構造的・意味的な要件、主にタグ付き構造ツリーと定義された読み上げ順序を課すため、支援技術に対してドキュメントがアクセシブルになる。パート2はパート1の一部の制限を緩和しオブジェクトストリームとJPEG 2000を許可する。パート3はさらに任意の埋め込みファイルを許可し、これは電子請求書フォーマットが、人間が読めるページと並んで機械可読なXMLを運ぶために使うものである

アーカイブされたスプレッドシートにとって、PDF/A-2bは実用的な既定値である:アーカイブに広く受け入れられており、レベルAがセルのグリッドに課すタグ付けの規律を要求せず、200ページのワークブックエクスポートが肥大化するのを防ぐコンパクトな構造を許可する。アーカイブがソースデータも添付として保持しなければならない場合はパート3を選ぶとよく、これはエクスポーターがAddAttachmentを通じてサポートしている

ほとんどの人が引っかかるフォントの規則

PDF/Aファイルが描画するすべてのグリフは埋め込みフォントに由来しなければならない。これは、それ以外は正しいエクスポートが検証に失敗する最も一般的な単一の理由であり、その失敗のしかたは微妙である:作成したマシンにはそのフォントがインストールされているため、そのマシン上ではファイルは正しく見えてしまう

HotXLSは使用するフォントのTrueTypeサブセットを埋め込むが、フォントが解決できない場合のためにベース14フォールバックパスが存在し、ベース14フォールバックは定義上埋め込まれない。アーカイブ用出力では、フォールバックパスが決して使われないよう明示的なUnicodeフォントファイルを設定すること。サブセット化とフォールバックチェーンの仕組みについてはTrueTypeフォントのサブセット化で説明されている。実務上の規則は、自社のフォントがインストールされていないマシンでエクスポートをテストすることである

HotXLS Delphi エクスポートにおける PDF/A フォントルールの図。解決済みフォントはどこでも検証に合格する埋め込み TrueType サブセットになり、base-14 フォールバックは決して埋め込まれずフォントのないマシンで失敗
解決できないフォントは、決して埋め込まれない base-14 フォントへフォールバックします。だからこそ、明示的な Unicode フォントファイルを設定し、社内フォントのないマシンでテストしてください

エクスポーターが保証すること、そして保証しないこと

ここでは自信ありげに聞こえることよりも正確であることの方が重要である。このエクスポートはPDF/Aの識別装置——出力インテント、埋め込みICCプロファイル、pdfaidメタデータ、適切なバージョンヘッダー——を生成し、テキストを埋め込み経路に通す。しかし自分自身の出力に対して完全な検証ツールを実行するわけではないため、透明性、特定の注釈タイプ、オプショナルコンテンツに関する規則など、仕様内のあらゆる禁止事項を強制するわけではない

スプレッドシートのエクスポートではそうした構造がめったに現れないため、実用上の成功率は高い。しかし高いことは保証されていることと同じではなく、本物のアーカイブパイプラインにとって正しいアーキテクチャは、エクスポートしたうえで独立したツールで検証し、検証失敗を警告ではなくパイプラインエラーとして扱うことである。PDFドキュメントに対する同様の責任分担についてはPDF/Aプリフライト検証で説明されている

レイアウトもアーカイブとしての忠実性の一部である

技術的には適合していても視覚的に読めないアーカイブされたスプレッドシートは、その本来の仕事に失敗している。ページ設定は日常の印刷よりもアーカイブ用エクスポートにおいてより大きな比重を持つ。なぜなら後になって誰もそれを再レイアウトできないからである

3つの設定が元を取る価値を持つ。幅に合わせるフィット設定は、14列幅のテーブルが2列ずつ7ページに分かれて届くという典型的な失敗を防ぐ。ヘッダー行の繰り返しは、どのページも単独で読めるようにしておく。そして明示的な印刷範囲は、実データの右側にある作業用メモを除外する。印刷とページ設定の制御一式は保護、ページ設定、印刷で扱われている

// export前に適用したarchive-ready page setup
Sheet := Book.Sheets[0];
Sheet.PageLandscape := True;
Sheet.FitToWidth := 1;
Sheet.FitToHeight := 0;                  // 必要なだけのpage height
Sheet.SetPrintArea('A1:N480');
Sheet.PrintTitleRows := '$1:$3';

// archiveにもMetadataが必要
Book.Title := 'Quarterly results 2026 Q2';
Book.Author := 'Finance';

最初のバッチを実行する前のチェックリスト

ファイルが自身を識別しているか確認すること:何も解凍する必要はなく、PDFをテキストエディタで開き、pdfaidのパートと適合エントリ、そしてGTS_PDFA1出力インテントを探すだけでよい。フォントを確認すること:ドキュメント内のすべてのフォントが埋め込み済みと報告されているかを確認する。見た目を確認すること:エクスポートされたページを印刷したコピーと比較する。なぜなら、テキストを気づかれないまま4ポイントまで縮小してしまうページ合わせ設定は、適合してはいても役に立たないからである

そのうえで代表的なサンプルに対して独立した検証ツールを実行し、その報告書を保管すること。アーカイブはファイルだけでなく検証の証拠を求めることが増えており、それをエクスポート時点で生成しておく方が、何年も後に再構築するよりはるかに安上がりである。日常的な非アーカイブ用のエクスポート経路とそのレンダリングオプションについてはワークシートPDFエクスポートを参照されたい

アーカイブ用エクスポート、ページ設定、そしてその背後にあるレンダリングエンジンは、DelphiおよびC++Builder向けの1つのライブラリにまとめられている。機能一覧の全体はHotXLS Delphiスプレッドシートコンポーネントページにある

HotXLS Delphi PDF/A 出力のエクスポート後検証アーキテクチャの図。エクスポーターが識別装備を書き、独立したバリデーターがファイルをアーカイブへ振り分けるかパイプラインエラーを発生させる
エクスポーターが識別の仕組みを組み立て、独立したバリデーターが適合を証明します。検証に失敗すればバッチは止まり、警告をログに残すだけでは済みません