動的配列
動的配列は、1 つの数式が複数の値を返し、その結果が周辺セルに spill(スピル)する仕組みです。数式テキストを保持する起点セルと、計算結果が広がるスピル範囲の組で表現します。Formulon はスピルの形状、依存関係、衝突挙動を再計算の一部として管理します。
用語: spill / spill range
動的配列数式が複数の値を返したときに広がる矩形領域です。左上の起点セルが数式テキストを持ち、それ以外のセルは起点の結果を受け取り、独立した数式は持ちません。
用語: anchor cell
動的配列数式の本体を保持するセルです。起点セルを編集または消去するとスピル全体が変化します。API から起点以外のセルへ書き込むこともできますが、その時点で既存のスピル範囲が解除され、起点セルが再計算待ちになります。次の再計算では、セルを空白に戻すとスピルが再生成され、値を残すと起点セルが #SPILL! になります。
旧来の CSE 配列数式
Ctrl+Shift+Enter(CSE)で入力した旧来の配列数式は、固定されたブロック全体に 1 つの数式として保存されます。起点以外のセルへ値、文字列、数式、空白を書き込むと kPreconditionFailed で失敗し、ブロックは変わりません。起点セルへの書き込みはブロック全体を置き換えます。ブロック内のすべてのセルがブロックの数式を返し、FORMULATEXT は {=...} の形で表示し、ISFORMULA は TRUE を返します。
挙動の概要
- スピル範囲は数式結果の形状(スカラー / 行 / 列 / 2 次元配列)から決まります。
- 形状が変わる数式は依存セルを再計算待ちにし、それらのスピル起点を再計算します。
- スピル範囲が非空セルを上書きしそうな場合は
#SPILL!を返し、データを黙って上書きすることはありません。 - スピルの勝者や従来の配列ブロックは決まった再計算順で解決されるため、同じワークブックは実行のたびに同じ結果になります。
- スカラーのエラーは配列に対してブロードキャストされ、エラーが捨てられずにすべての要素に現れます。
- 暗黙的な要素数の拡張(ブロードキャスト)で次元が合わない場合(例: 3 行と 5 行を混在)は、関数ごとの Excel エラー規則に従います。
- セル範囲の直接参照、算術 / 比較演算子、
IFは引数の形状に合わせてスピルします。直接参照した範囲の空白セルは0になります。 - スカラー関数は範囲の引数を要素ごとに評価します。範囲を返す組み込み関数は共通のスピル割り当てを通り、衝突とシート外判定を共有します。
@は暗黙の交差を適用し、数式の起点に対応する範囲 / 配列の値へ縮約します。- スピル演算子
#は、OFFSET、INDIRECT、CHOOSE、IF、括弧で囲んだ参照、LETで束縛した名前など、実行時に計算される起点セルを受け取れます。複数セルへ解決される起点セルは左上だけに暗黙縮約せず、#REF!を返します。
配列サイズの上限
数式が評価する配列は、形状や由来を問わず 107,374,182 要素までです。この値は Mac 版 Excel 365 で測定した境界で、A:CX+0(106,954,752 要素)は評価され、A:CY+0 と SEQUENCE(1048576,103)(108,003,328 要素)は数式全体の結果が数値 0 になります。この上限はどのプロファイルでも同じですが、Windows 版 Excel はより小さい配列でも評価を打ち切ります。SUM、AVERAGE、MIN、MAX、PRODUCT、COUNTA は、行全体・列全体に対する演算の結果を実体化せずに畳み込むため、大きな全行・全列の集計も上限内に収まります。
スピルする関数の例
=SEQUENCE(5)
=UNIQUE(A1:A100)
=SORT(A1:B20, 2, -1)
=FILTER(A1:C50, B1:B50 > 0)
=LET(x, A1:A10, x * 2)ここに挙げた数式は下のパネルで実行できます。上の表は evaluateFormulaArray() の結果で、隣に表示される形状は説明用に描いた図ではなく、エンジンが算出した行数 x 列数です。その下のシートは実物の formulon-cell グリッドで、同じ数式を D2 に書き込んで再計算した状態です。選択されているスピル範囲は spillInfo() が返した矩形です。「スピル先を塞ぐ」を押すとその矩形の中に値が 1 つ入り、起点セルは #SPILL! になって結果は 1 つも書き込まれません。デモ側の演出ではなく、上で述べた衝突の規則がそのまま現れています。
ダイナミック配列とスピル
配列を返す数式を、まず evaluateFormulaArray() でワークブックを書き換えずに形のまま取得し、次に下のシートの実際のセルへ書き込んで spillInfo() でスピル範囲を確認します。
本物の Formulon エンジン (WASM) がこのページ内で動作します。データは送信されません。
デモを試す順序
まず =SEQUENCE(3,4) を選び、プレビューの形状を確認します。シートへ書き込んだ後に右下を塞ぐと、結果が一部だけ書かれることなく起点セルが #SPILL! になります。塞いだセルを空にしてから =FILTER(A2:B6,B2:B6>4) へ切り替え、A 列または B 列の入力値を編集してください。プレビューはすぐ変わります。書き込んだ数式のスピル範囲は再計算時に更新されます。
再計算との連携
再計算エンジンは起点セルごとに以下のスピルメタデータを保持します。
| フィールド | 用途 |
|---|---|
| 起点アドレス | 数式本体のシート / 行 / 列 |
| 結果形状 | 直近の成功時の行数 x 列数 |
| スピルエラー | スピルが成立しなかった場合の #SPILL!、それ以外は null |
| 範囲の依存元 | スピル内のいずれかのアドレスを参照しているセル |
形状が変わると、旧スピル矩形・新スピル矩形いずれかにかかるすべての依存セルが再計算待ちになります。
スピル状態の検査
spillInfo(sheet, row, col)(Python は spill_info())は、セルがスピルの起点かどうかと、その矩形の起点とサイズを返します。MCP の formulon_trace ツールはセッションから参照元 / 参照先 / スピル情報を読み取れます。#SPILL! の原因になっているセルを探すときに使ってください。
互換性の注意
動的配列の挙動はワークブック単位のフラグや、同じシート内に旧来の CSE(Ctrl+Shift+Enter)配列数式が混在しているかどうかにも依存します。両方が混在するワークブックでは、同じファイルを対象の Excel で計算した結果と比較してから使ってください。