HotXLS ドキュメント

外部ワークブック参照

概要

スプレッドシートモデルは多くの場合、相互参照数式を使用して二次ワークブックからデータを取得します。HotXLS は、BIFF8(古典的 XLS)と OpenXML (XLSX) の両方のドキュメントで外部ワークブック参照の解析、書き込み、保持をサポートします

ライブ ワークブック ワークスペース

lxWorkbookWorkspace の TXLSWorkbookWorkspace は、ライブな外部ワークブックに対する共有識別子と登録の中核です。TXLSWorkbook と TXLSXWorkbook はどちらも CreateWorkspaceWorkbook を公開し、それぞれの数式エバリュエーターが使用する ExternalWorkspace を所有します。TXLSXWorkbook 経由で開いた ODS ワークブックも、同じアダプターを通じて OpenDocument エンジン種別を報告します

var
  Host, Target: TXLSXWorkbook;
begin
  Host.ExternalWorkspace.Add(
    '..\Data\Target.xlsx',
    '..\Data\Target.xlsx',
    'C:\Models\Host.xlsx',
    Target.CreateWorkspaceWorkbook);

  // The compatibility facade maps an unambiguous name to the
  // relationship target already stored in Host.ExternalLinks
  Host.RegisterExternalWorkbook('Target.xlsx', Target);

  // The matching call revokes a facade-level registration
  Host.UnregisterExternalWorkbook('Target.xlsx');
end;

クラシック ワークブックも、TXLSWorkbook をターゲットにして同じ互換性メソッドを使用できます。RegisterExternalWorkbook と UnregisterExternalWorkbook が管理するのはファサード レベルの名前対応付けだけであり、ワークスペースの登録そのものは ExternalWorkspace.Remove と Clear が取り消します。エンジンが異なる呼び出し元は、クラシック、XLSX、ODS のいずれのアダプターも ExternalWorkspace に直接追加できます

  • 識別子の正規化は字句レベルで行われ、大文字小文字を区別せず、パスと拡張子を保持し、所有元のソース識別子を基準に相対ターゲットを解決し、ドット セグメントを圧縮します。ファイル システムやネットワークへのアクセスは一切行いません
  • 完全一致の識別子と明示的なエイリアスが最初に解決されます。ファイル名だけのルックアップは、接続中の登録とちょうど 1 件だけ一致した場合にのみ成功し、それ以外では Resolve が xlswrsConflict を返します
  • Add は、同一キー、エイリアス、重複ワークブックの衝突を拒否します。異なる完全パスと異なる拡張子は共存できます
  • Remove と Clear は登録を取り消します。また、クラシックまたは XLSX のターゲットを直接破棄すると、そのアダプターが切断され、モデルを解放する前にアクティブなリーダーを待機します
  • 外部ワークシートは、1 始まりの位置によるフォールバックより先に、宣言された名前で解決されます。そのため、ターゲット ワークブックのシート順がソース側のリンク ディレクトリと一致する必要はありません
  • 数式エバリュエーターは、解決できたライブ ワークブックをまず読み、その後でホスト ファイルの型付きキャッシュにフォールバックします。クラシック XLS のホストはスパースな XCT と CRN の値をデコードし、XLSX のホストはパッケージ モデルが既に保持している外部リンク キャッシュを使用します
  • OnLoadWorkbook はオプションの制御付きリソース要求です。既定値は nil であるため、アプリケーション コードがこのポリシーを明示的に提供しない限り、再計算がファイル システムやネットワークへアクセスすることはありません
  • 正規化された各識別子について、ローダーは ResetLoadAttempts まで多くとも 1 回しか呼び出されません。同時に発生した最上位の要求は、型付きの not-found やエラーの結果を含めて処理中の結果を共有し、同じリソースを繰り返し開くことはありません
  • MaxLoadDepth の既定値は 16、MaxWorkbookCount の既定値は 64 です。同一識別子の再入、すでに処理中の識別子へのネストした依存、深さの枯渇、ワークブック数の枯渇は、読み込みサイクルをブロックすることなく型付きの診断を返します
  • ODF の外部ソース IRI は、URI スキームや引用符で囲まれた文字を含めて完全な字句通りの識別子として扱われますが、暗黙的なファイル アクセスやネットワーク アクセスを許可することはありません
  • 識別子の衝突は #REF! のまま残るため、経路のあいまいさが古いキャッシュ データに隠れることはありません。キャッシュされたセルが欠落している場合、空の値になるのは、ファイルがそのシートの有効なキャッシュを宣言しているときだけです

Resolve は登録済みのルックアップを行ってから、オプションの制御付き読み込みを実行します。結果は TXLSWorkspaceResolveStatus (xlswrsResolved、xlswrsNotFound、xlswrsConflict、xlswrsDisconnected、xlswrsLoadNotFound、xlswrsLoadLimit、xlswrsLoadLoop、xlswrsLoadError) として返されます。さらに ResolveWithLoader は TXLSWorkspaceLoadDiagnostic も返します。これは TXLSWorkspaceLoadDiagnosticCode と TXLSWorkspaceLoadResponseStatus (xlswlrsNotFound、xlswlrsResolved、xlswlrsError) の組み合わせで、not found、ローダー エラー、切断済み、深さまたはワークブック数の上限、識別子の再入、同時依存、登録の競合という結果を区別します。ローダーのコールバックは TXLSWorkspaceLoadRequest (識別子、深さ、登録数、上限) を受け取り、TXLSWorkspaceLoadResponse で応答します

Recalculate は TXLSWorkspaceRecalcStatus を報告し、オプションで TXLSWorkspaceRecalcResult の内訳も受け取れます。エバリュエーターはセルごとの参照元を TXLSWorkspaceRuntimeLookup (xlswrlInactive、xlswrlResolved、xlswrlFallbackCache、xlswrlError) として記録するため、診断時にライブ読み取りとキャッシュ フォールバックを区別できます

IXLSWorkspaceWorkbook アダプターは、EngineKind (型 TXLSWorkspaceEngineKind: xlsweClassic、xlsweOpenXml、xlsweOpenDocument)、SourceIdentity、InstanceIdentity、Generation を公開し、IsConnected で接続状態を判定し、TryGetCellValue でセルを 1 つ読み取り (値、欠落、無効な参照、切断、エラーのいずれかを表す型付き TXLSWorkspaceCellStatus に加えて使用範囲外フラグを返します)、Recalculate でモデルを更新し、Disconnect でワークブック モデルから切り離します

レジストリには、1 つの登録済み識別子に追加の名前を束ねる AddAlias、例外を発生させないルックアップ バリアントの TryResolve、そして対象を 1 つに絞り込む前に同じベース名を共有する接続済み登録の数を事前に確認できる BaseNameMatchCount が追加されています

ワークブック間の依存関係グラフ

BuildDependencyGraph は登録済みのすべてのワークブック アダプターのスナップショットを取得し、クラシック XLS、XLSX、ODS の各モデルから数式ノードを抽出して、1 つの TXLSWorkspaceDepGraph にまとめます。登録済みのアダプターが 1 つでも依存関係メタデータを提供できない場合、このメソッドは False を返し、部分的なグラフも作成しません

  • 各数式ノードは、正規形のワークブック識別子、ワークシート名と 1 始まりのワークシート位置、0 始まりのセル位置、配列出力の矩形、揮発性、未解決参照の状態を保持します
  • セル参照と矩形範囲参照は、ターゲット ワークブックとワークシートの正規形の識別子を保持します。列全体、行全体、シート全体の参照は、数百万個のセルに展開されるのではなく、1 つの区間のまま維持されます
  • ローカルの定義名はシンボリックな依存としてクエリ可能なまま残り、定義を静的に解決できる場合は、具体的なセルや範囲の依存関係へ展開されます
  • 外部の定義名は、DDE、OLE、ユーザー関数のメタデータをワークブック名として扱うことなく、外部リンク スロット、宣言された名前、オプションのワークシート スコープ、正規形のターゲット識別子を保持します
  • FindDependentsOfCell とグラフ エッジの構築は、最大終端プルーニング付きの行区間ツリーを使用します。LastRangeCandidateChecks と EdgeCandidateChecks は、パフォーマンス検証のために正確な矩形チェックの実行回数を公開します
  • 数式の抽出はワークブックの読み取りリースの下で実行され、実体化された数式オブジェクトだけを走査します。そのため、パックされた値ストレージはパックされたままになり、グラフの作成によってワークブックの世代が変わることはありません

スケジュールされた再計算

Recalculate は共有グラフを保持し、ワークスペースの登録またはワークブックの数式依存ジェネレーションが変わったときにだけ再構築します。値のジェネレーションは新しいダーティ パスの起点となり、ダーティ状態はワークブック間の依存エッジを通じて伝播します

var
  RecalcInfo: TXLSWorkspaceRecalcResult;
  Status: TXLSWorkspaceRecalcStatus;
begin
  Status := Workspace.Recalculate(RecalcInfo);
  if Status <> xlswrcOk then
    HandleWorkspaceCalculation(Status, RecalcInfo);
end;
  • 強連結成分は数式セルを対象に計算されるため、ワークブック同士が双方向にリンクしていても、セル レベルの依存パスがループを形成しない限り、グラフは非環式のままです
  • 実際の循環のメンバーと、循環によってブロックされたダーティな子孫は無効化され、トポロジカル順序から除外されます。これにより、古いキャッシュ値が成功結果として提示されるのを防ぎます
  • 揮発性の参照や静的に未解決の参照は、正しさのために必要な保守的なダーティ動作を強制します。一方、安定したグラフでは、以前の依存関係の計算が再利用されます
  • 1 回のパス内の外部読み取りは、ワークブック インスタンス、ワークシート、行、列が完全一致するキャッシュを使用します。スケジュールされた数式は評価の前に出力範囲を無効化するため、後続の依存セルは新しい値を観察します
  • パス ローカルのキャッシュがリソースへの権限を与えることはありません。ライブ解決のソースは登録済みワークブックと、オプションの呼び出し元制御ローダーだけであり、その後ろに型付きファイル キャッシュ、そして #REF! が続きます
  • TXLSWorkspaceRecalcResult は、グラフが再構築されたかどうかに加え、ダーティ、評価済み、無効化、循環、ブロック、キャッシュ ヒット、キャッシュ ミスの各カウントを公開します
  • ステータスは、成功、未サポートのアダプター、切断されたワークブック、循環参照、計算エラー、パス中のワークスペース変更を区別します
  • 同じワークスペースに対する Recalculate の呼び出しは直列化されるため、2 つの計算セッションが共有グラフやワークブック キャッシュを同時に変更することはありません
  • パスの実行中に Remove や Clear が呼び出されても安全です。パスは安全なアダプター スナップショットを保持し、削除済みの登録を逆参照する代わりに xlswrcWorkspaceChanged を返します
  • ワークスペースの破棄はアクティブなパスの完了を待機します。一方、登録済みワークブックの破棄はそのアダプターを切断し、それ以降の解決を安全に失敗させます
  • ローダーの失敗と not-found の結果は、正規化された各識別子について ResetLoadAttempts まで 1 回だけキャッシュされます。失敗した計算は、明示的な再試行のためにローカルのダーティ状態を保持します
  • グラフが保持されるため、変更のない後続のパスのコストは数式の数ではなく登録済みワークブックの数に比例します。非再帰的な強連結成分解析とコンパクトな範囲エッジにより、深く広いモデルも、実体化された数式メタデータの量で収まります

外部の定義名の切り離し

ConvertExternalDefinedNamesToRefErrors は、TXLSWorkbook と TXLSXWorkbook の両方で同じ公開操作を提供し、ネイティブの #REF! に置き換えられたワークブック スコープおよびワークシート スコープの定義の数を返します

var
  Converted: Integer;
begin
  Converted := Workbook.ConvertExternalDefinedNamesToRefErrors;
  // External-link parts and ordinary cell formulas remain intact
end;
  • クラシック XLS の選択には、コンパイル済みの BIFF 参照トークンと XTI のサポート ワークブック識別子が使われるため、同一ワークブック内の 3 次元参照や不確実なトークン ストリームは変更されません
  • XLSX の選択は、リレーションシップ ドキュメント順の数値ワークブック スロットを構文解析レベルで識別して使用し、ワークブックの外部リンク パーツだけを受け入れます。DDE、OLE、未解決のスロット、テーブル参照、文字列内の角かっこテキストは除外されます
  • すべての置き換えは最初の変更の前に準備され、1 回の書き込み操作としてコミットされます。2 回目の呼び出しは冪等です
  • 名前テキスト、ワークブックまたはワークシートのスコープ、可視性、コメント、マクロ フラグと組み込みフラグ、不明な XLSX 属性、外部リンク ディレクトリは、変換後もラウンドトリップ後も利用できます
  • 不正または未サポートの定義は、推測で書き換える代わりに、可能な限りバイトまたはテキストを保持したうえで xlsDiagnosticDefinedNameConversionSkipped 診断を追加します
  • 依存する数式は対応する Excel エラー値に再計算されます。その一方で、通常の直接外部数式の有効なキャッシュ結果は、ライブ ワークブックが後で切断された場合でも利用できます
  • この操作は Excel 固有のものであり、OpenDocument の名前数式セマンティクスを再解釈することはありません

古典的 XLS の外部参照

古典的 XLS ワークブックでは、外部リンクは EXTERNALBOOK および EXTERNNAME レコードを使用してグローバルディレクトリブロックに格納されます。HotXLS はファイルの読み書きサイクル中にこれらのディレクトリを維持し、リモート範囲参照が変更ループを経ても保持されるようにします

XLSX の外部リレーション

OOXML ワークブックでは、外部リンクの対応付けはリレーションシップパーツを通じて管理されます。以下のサポートインターフェースの詳細を確認してください