技術記事

HotXLS で Excel 画像からタグ付き PDF の Figure を作る

HotXLS が自動タグ付けを有効にしてワークシートを PDF へエクスポートするとき、代替テキストを運ぶワークシート画像は、Unicode の /Alt エントリ、ページローカルな密なマークコンテンツ識別子、正確な親ツリーエントリを持つ、独立した /Figure 構造要素として出力されるようになりました。代替テキストのない画像は装飾的なアーティファクトのままにとどまり、チャートもアーティファクトのままです。この正確なスコープは重要です。情報を持つ画像をスクリーンリーダーが到達できるようにし、そして完全な PDF/UA 適合と同じものではないからです

その背後の仕組みは機能の説明より面白いものです。そのうち 2 つは、黙って構造的に有効でありながら構造が誤ったコンテンツを指す PDF を生み出す類の細部だからです

何が情報を持つ画像と数えられるか

空でない AltText だけです。TXLSXImage.AltText プロパティは、画像の非視覚プロパティの OOXML descr 属性を往復させます。ユーザーが代替テキストペインへ入力したテキストを Excel が格納する場所です。作者がその画像を装飾ではなく情報を運ぶものと考えたことを示す、ファイル内の唯一の信号です。したがってエクスポーターが信頼する唯一の信号です

2 つのすれすれの候補は、意図的に受け付けません。説明とは別に格納されるタイトルフィールドは代わりになりません。タイトルはオブジェクトの名前であって、テキストによる等価物ではないためです。それを /Alt へ昇格させると、自動チェックを通りながら、スクリーンリーダーに「画像 3」と告げる文書が生まれます。空の説明も、プレースホルダーで埋めるべき隙間ではありません。画像がアーティファクトのままであることを意味し、ロゴや区切り罫線にとって正しい帰結です。チャートも当面はアーティファクトのままです。チャートのテキストによる等価物はそのデータであり、系列からそれを合成するのは抽出ではなく創作になるからです

空でない AltText を持つ画像は、独自の MCID を伴う PDF の Figure 構造要素としてエクスポートされる様子。空の説明とチャートはアーティファクトのまま。
AltText の中の作者の説明だけが、情報を持つ画像の信号です。タイトルだけが代替テキストになることは決してありません
uses
  lxHandleX, lxPDF;

var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
  Exporter: TXLSPDFExport;
  I: Integer;
begin
  Book := TXLSXWorkbook.Create;
  try
    Book.Open('regional-review.xlsx');
    Sheet := Book.Sheets.ByPos[0];

    // エクスポート前に監査する:説明のない画像は
    // 装飾的なアーティファクトとしてエクスポートされる
    for I := 0 to Sheet.Images.Count - 1 do
      if Sheet.Images[I].AltText = '' then
        Sheet.Images[I].AltText := DescribeImage(Sheet.Images[I].Name);

    Exporter := TXLSPDFExport.Create;
    try
      Exporter.TagMode := xlsPdfTagsAutomatic;
      Exporter.DocumentLanguage := 'en-US';
      Exporter.SaveAsPDF(Sheet, 'regional-review.pdf');
    finally
      Exporter.Free;
    end;
  finally
    Book.Free;
  end;
end;

ページに単一の MCID アロケータが必要なのはなぜか

親ツリーはマークコンテンツ識別子をインデックスとする配列であり、2 つのアロケータは同じスロットを主張する 2 つのエントリを生むからです。タグ付き PDF はコンテンツと構造を双方向に結び付けます。コンテンツ側では、ページコンテンツストリームの区間が、そのページ内で一意な /MCID 番号を運ぶ BDCEMC オペレータで包まれます。構造側では、ページ辞書が文書の /ParentTree の行を名指す /StructParents キーを運び、その行は、インデックス n の要素が MCID n を所有する構造要素である配列です

ワークシートページはテーブルセルを含み、今では figure も含みます。セルのタグ付け器が識別子をゼロから数え、figure のタグ付け器もゼロから数えるなら、最初の figure は最初のセルがすでに所有しているスロットを主張します。でき上がったファイルについて、パーサーが拒否するほどの不整合は何もありません。構造ツリーは無傷であり、マークコンテンツはバランスしており、バリデータは親ツリーを持つ文書を見ます。スクリーンリーダーが得るのは、画像として告げられるテーブルセル、またはセルのテキストとともに告げられる画像です。したがってエクスポーターは、両方のタグ付け器が共有する 1 つのページレベルカウンタから割り当て、ページレコードはページオブジェクト番号が判明した後にのみ確定します。親ツリーの行は、それが参照するページが同一性を得る前に書けないからです

独立したセルと figure のタグ付け器が親ツリーのスロット 0 で衝突する様子。1 つのページレベルの MCID カウンタが、すべてのマークを 1 つの所有者へ対応させ続ける。
衝突したファイルは今も構造バリデータを通ります。誤っているのはスクリーンリーダーの読み上げだけです

Figure は可視インスタンス全体を包まなければならない

自明な配置は、画像 XObject を起動する Do オペレータを包むことです。画像を描くのがそのオペレータだからです。しかし十分ではありません。ワークシートの画像は、背後に影を伴い、周囲にクリッピングパスを伴って描かれることが多く、それらのマークは可視オブジェクトの一部です。/Figure スコープの外に置かれると、それらはマークなしコンテンツになります。構造監査が印を付けるまさにその状態です

したがってマークコンテンツのスコープは、影の前に開き、画像の描画の後に閉じ、クリップもカバーします。共有は、共有が正しいところでは保存されます。同じ画像ペイロードを表示する 2 つのセルは今も 1 つの画像 XObject を参照します。それはリソースレベルの最適化であり、セマンティクスとは何の関係もないからです。各可視インスタンスが得るのは、独自の MCID と独自の構造要素です。異なる場所に現れた同じロゴの 2 つの出現は、読み手が出会う 2 つのものだからです。画像の配置とこれらのオブジェクトを位置付ける EMU ジオメトリは、画像ジオメトリの記事で扱っています

BDC のマークが影とクリップの前に Figure スコープを開き、Do の画像描画の後に EMC が閉じる様子。可視インスタンス全体をカバーする。
画像オペレータだけを包むと、影とクリップがマークなしコンテンツとして残ります。セル間のリソース共有は保存されます

ワークシートページ上の読み順

読み順は、エクスポーターが決めなければならない判断です。スプレッドシートには、文書のような書かれたフローがないからです。採用された規則は安定していて説明しやすいものです。各ページについて、まずテーブル、次に描画順に figure が続きます。読み手は、ページの表形式のコンテンツを聞いてからその画像を聞きます。描画オブジェクトがたまたまファイル内で占めていた位置で画像が差し挟まれるのではなく

この順序は文書ごとではなくページごとであり、数十ページに分割されるワークブックでは重要です。各ページの構造ブランチは自己完結しているため、ページ間を移動する読み手は、前のテーブルへ飛び戻りません。そもそもシートがどうページ分割されるかを制御する必要があるなら、ページ設定と印刷範囲の相互作用は保護とページ設定の記事に述べています

これが保証するものと、しないもの

これが保証するのは、情報を持つ画像が作者が供給した説明とともに支援技術へ届くこと、そしてコンテンツから構造へのマッピングが、単に存在するだけでなく正しいことです。出力を PDF/UA 適合にはしません。そのように述べることは、実装が支えられない主張になります。チャートは今もアーティファクトであり、完全な適合声明には、すべての構造型、すべてのフォント、そして文書メタデータ全体の監査が必要です

要件がアクセシビリティの改善ではなくアーカイブや適合のプロフィールであるなら、それは別のエクスポート構成と別の確認の集合であり、PDF/A アーカイブエクスポートの記事に述べています。2 つは組み合わせられますが、答える相手は異なる監査者です

レポートパイプラインへの 1 つの実務的な提案があります。代替テキストは、エクスポート時ではなく、ワークブックが生成される時点で監査してください。ジェネレータは、各チャート画像や埋め込み図式が何を表すかを知っており、本物の説明を AltText へ書き込めます。エクスポート時のパスが教えられるのは、説明が欠けているということだけです。HotXLS は Excel 依存なしに、Delphi と C++Builder から XLS、XLSX、ODS、CSV をネイティブに読み書きし、エクスポート構成のオプションは、HotXLS Delphi spreadsheet component の製品ページに一覧があります