技術記事

HotXLSでメタデータのみと選択的シート読み込みを行う方法

HotXLSはXLSXブックを開き、ワークシートのセルを1つもパースしないことができる。TXLSXWorkbook.MetadataOnlyはブックプロパティ、定義名、シート名と可視状態、スタイル、テーマ、コネクション、外部リンクを読み、セルXMLの前で止まる。ワークブックのディレクトリの中身を知る必要があるスキャナにとって、これは分と秒の差になる

3つの関連スイッチが全体を完成させる。SelectedSheetsは名指しされたサブセットのセルだけをパースし、LoadSheetは後から元のアーカイブからスキップされたシートを実体化し、PreserveRawPartsは変更されていないパートの圧縮バイトを保存時にそのまま通す。これらを組み合わせれば、「ブックを開く」という1つのオールオアナッシング操作を、スコープを絞れるものに変えられる

1つのセルもパースせずに何を知れるのか

ほとんどの発見タスクが必要とする以上のものだ。Openの前にMetadataOnlyを設定しておくと、ブックはシート名と可視状態、定義名、ドキュメントプロパティ、スタイルとテーマ、外部リンク、コネクションを保持して戻ってくる。シートは、セルゼロのオブジェクトとして存在する

それはまさに、カタログ、監査、ルーティングの判断が依る情報だ。どのブックがTaxRateという名前を定義しているか。どれが非表示シートを持つか。どれがすでに廃止されたサーバーへリンクしているか。すべてのファイルを完全に読み込んでこれらに答えるのが、夜のジョブを一晩中走るジョブにしてしまう方法だ

var
  Workbook: TXLSXWorkbook;
  I: Integer;
begin
  Workbook := TXLSXWorkbook.Create(nil);
  try
    Workbook.MetadataOnly := True;      // set before Open
    Workbook.Open(FileName);
    for I := 1 to Workbook.Sheets.Count do      // Sheets[] is 1-based
      if not Workbook.Sheets[I].Visible then
        Report.Add(FileName + ': hidden sheet ' +
          Workbook.Sheets[I].Name);
  finally
    Workbook.Free;
  end;
end;

40のうち2つのシートだけを読み込む

SelectedSheetsはシート名のTStringListだ。空でないとき、Openは名指しされたシートのセルXMLだけをパースし、それ以外の各シートは正しい名前と可視状態を保ちつつセルを保持しない。空のリストは、すべてを読み込むという以前の挙動を意味する

MetadataOnlyとの相互作用は、後ろ向きに取ると当惑する空のブックを生むので、はっきりと述べておく価値がある。MetadataOnly = Trueは選択を上書きし、すべてのシートをスキップする。どちらか一方を使うこと。発見はメタデータのみを使い、的を絞った作業は選択を使う

Workbook.SelectedSheets.Add('Summary');
Workbook.SelectedSheets.Add('Q3 Detail');
Workbook.Open('consolidated-2026.xlsx');
// Later, when the user opens a tab you skipped.
// LoadSheet takes the 0-based position and needs the source file,
// so it does not work on a workbook opened from a stream
if Workbook.LoadSheet(ZeroBasedPosition) then
  Grid.Refresh;

LoadSheet(Index)はスキップされたシートを元のアーカイブからオンデマンドで実体化する。これこそ、このパターンをバッチだけでなくインタラクティブなアプリでも使えるものにする。ユーザーが見ているシートを開き、クリックされたときにほかを読み込む。アーカイブはまさにそのために開かれたままである。だからユーザーが別のシートを求める可能性がある限り、ブックを生かしておくこと

なぜラウンドトリップは触れてもいないパートを変えるのか

素朴な保存がすべてを再生成するからだ。テーマを展開し、オブジェクトモデルを構築し、シリアライズして戻し、再圧縮する。するとテーマについて何も変わっていないのにバイトが異なる。VBAプロジェクトやピボットキャッシュでは、それは無駄である以上に悪い。それらのパートはオブジェクトモデルが完全には表現しない構造を運ぶからだ

PreserveRawPartsは、SaveAsの間に変更されていないパートの圧縮表現をソースアーカイブから直接コピーすることでこれに答える。テーマ、VBAプロジェクト、ピボットテーブル、ピボットキャッシュは、変更されなかったときバイトとしてそのまま渡される。展開も再圧縮もなく、シリアライズのラウンドトリップで何かを失うリスクもない

コストは、あなたがすでに持っていた制約だ。ソースアーカイブは保存時にも利用可能でなければならない。ワークフローがファイルをメモリに読み込み、閉じ、1時間後に保存するなら、raw コピーのパスはコピー元を持たない。ブックのライフタイムの間ソースを到達可能に保つこと。これはLoadSheetが課すのと同じ要件だ

意図的に2度開く発見パイプライン

本番で働くパターンは、2つのパスを持ち、小細工を持たない。パス1はメタデータのみで開いて決定する。パス2は、意味のあるファイルを選択されたシートとともに開き直し、作業を行う。開き直しは無駄に見えるが、パス1が回避したものを数えれば納得できる。2回目のオープンだけがセルをパースし、しかもパス1が選んだシートだけをパースするのだ

// Pass 1: discovery
Workbook.MetadataOnly := True;
Workbook.Open(FileName);
Wanted := SheetsMatching(Workbook, 'Invoice');
Workbook.Free;

// Pass 2: targeted load
Workbook := TXLSXWorkbook.Create(nil);
Workbook.SelectedSheets.AddStrings(Wanted);
Workbook.Open(FileName);

Openの後にフラグをクリアしてメタデータのみのブックをインプレースで昇格しようとしないこと。フラグはオープン中に読まれる。後にクリアしても、セルXMLが訪問されなかったブックについて何も変えない

ほかの大ファイル向けレバーとの関係

選択的読み込みはパースするものを減らす。一度読み込まれたシートのコストは減らさないし、本当にすべてのシートのすべてのセルが必要な場合も助けない。そのケースでは、関連する作業はストレージ側にあり、行ブロックのセルストレージと区間スタイルオーバーレイのノートと、パース側の並列XLSXパースとメモリアロケータで説明されている。編集をまったく伴わない純粋なスキャンがタスクなら、ストリーミング直接リーダーはオブジェクトモデルを完全にスキップし、オブジェクトモデルを構築するあらゆる読み込み戦略を上回る

HotXLSはネイティブのDelphiとC++BuilderコードからXLSとXLSXを開き、Excelへの依存を持たない。だからサーバーサイドの発見ジョブは、自社の実行可能ファイル以外には何もインストールせずに走る。サポートされるフォーマットとライセンスについてはHotXLSスプレッドシートコンポーネントページを参照のこと