XTL 言語
この日本語訳は読みやすさのための補助資料です。仕様の正典は英語原文で、規範的な解釈の差異が生じた場合は英語版が優先します。
本ドキュメントは XTL 0.1 テンプレート言語のサーフェスを定義します。本文の記法はテンプレート作成者と実装にとって規範的(normative)です。
{{ ... }} テンプレートブロックの内容に対する形式文法は grammar.ebnf にあります。これはポーターおよびツール作成者のための非規範的な補助資料です。用語の定義は glossary.md を参照してください。
テンプレートブロック
テンプレート式は二重中括弧の中に書きます。
{{ expression }}
{{ と }} の直後・直前の空白には意味がありません。パーサーは正規化(normalization)の前に先頭・末尾の空白をトリムします。以下はすべて等価です。
{{ [name] }}
{{[name]}}
{{ [name] }}
{{
[name]
}}
演算子周辺の空白(例:{{ [a] + [b] }} と {{ [a]+[b] }})にも意味はありません。文字列リテラル内の空白は保持されます("hello world" のスペースはそのまま残ります)。
中身が空のテンプレートブロック({{ }} または空白のみ)は ADR-0021 によりパースエラーとなります(xl3/parser/empty-block)。
テンプレートブロックは {{ で開かれ、セルテキスト上で最初に現れる }} で閉じられます。デリミタスキャナは文字列リテラルを認識しません。すなわち "..." リテラル中の }} はブロックを閉じます(ADR-0051)。値の中に }} を含めたい作成者は、それを __config__[key] に保持し、{{ __config__[key] }} で参照してください。式本体中の " の数が奇数であるもの(リテラルの不整合。ほぼ常に埋め込まれたデリミタによって発生)は xl3/parser/unbalanced-literal を発生させます。
データブロック
シート上の データブロック は、ソース行をレンダリングするときにエンジンが展開する矩形です。2 つの次元を持ちます。
- 行範囲
[r_start..r_end]— 各行に少なくとも 1 つ の データ行セル({{ ... }}本体が、集計関数の外側で少なくとも 1 つの[Column]を参照するセル)が含まれる、連続行の最大範囲です。2 つのデータ行の間に非データ行([Column]参照を持たない行)があると、そこでブロックは閉じます。 - 列範囲
[c_start..c_end]— ブロックの行範囲内にある任意の{{ ... }}式セルすべての bounding box を、隣接する非空セルを通って外側へ拡張したものです。marker セルに直に隣接するネイティブ Excel 数式({ formula: "..." })または静的値はブロックの内側です。完全に空の列で隔てられた非空セルは外側です。
矩形内のセルは block cells です。矩形の外側にある同一シート上のセルは outside cells です(ADR-0066)。
シートあたり 1 ブロック(0.x)。 XTL 0.x では、1 シートに高々 1 つのデータブロックがあります。パーサーが [Column] データ行セルの disconnected cluster を 2 つ以上検出した場合、パース時点で xl3/expression/bracket-outside-block を発生させ、2 つ目の cluster の開始行を示します。multi-block サポート(境界を曖昧にしないための明示的な @block directive)は将来の ADR に繰り延べです。
ブロック展開セマンティクス(レンダリング側。evaluation.md の「Render Phases」で規範化):
- block cells は展開後の行へクローンされます —
(r_end - r_start + 1)個のテンプレート行ごとに 1 レコードです。 r < r_startの outside cells は元の位置に残ります(ブロックよ り上の header / configuration 行)。r >= r_startの outside cells は、ブロック展開で splice が行を挿入しても、元の行rに残ります。下方向へシフトしません(NOT)。数式テキストは逐語的に保持されます。- 内側列にあり、かつ
r > r_endのセル(つまり、データと同じ列に "Total" ラベルや footer 数式を置く footer-row ケース)は、展開済みデータブロックの下に来るよう(N - 1) × (r_end - r_start + 1)行だけ下へシフトします。
この非対称性 — ブロックより下の内側列セルはシフトし、同じ行にある外側列セルはシフトしない — は意図的です。メインデータブロックの右または左に置かれる、ブロック非依存の並列レポート領域である一般的な「サイド集計表」パターンを、別シート宣言なしで支えるためです。
ラベルと数式のペアを一緒にシフトさせたい場合(例: A4='footer'、B4=LOWER(A4))、作成者は両方のセルをブロックの列範囲内に置きます。marker セルがたまたま B まで届かない場合(例: A2 のみに marker がある場合)、B は外側となり A のシフトに追従しません。回避策は、B2 に marker を追加すること({{ "" }} のような trivial literal expression でも可)、または — 将来のリリースで利用可能になれば — 明示的な @block A:B 形式を使うことです。
ソース列
ソース列はブラケット構文で参照します。
{{ [Customer] }}
{{ [Customer Name] }}
{{ [Units Per Case] }}
[ と ] の間のテキストは、囲む空白をトリムした後の正確なソース列名です。列名にはスペース、英字、数字、句読点を含めることができます(MAY)。ただし ] と改行は除きます。
セル内の {{ Customer }} のような裸の名前はソース列参照ではありません。裸の名前はシートおよびファイルグループキー専用です。
ADR-0054 により、テンプレートブロック内の裸の識別子は以下の順序で解決され、解決できない場合は xl3/expression/unknown-name が発生します。
| コンテキスト | 解決順 |
|---|---|
output_file_pattern | ファイルグループキー → __inputs__[name] → __config__[name] |
| シート名パターン | シートグループキー → __inputs__[name] → __config__[name] |
| データセル | 外側のファイルグループキー → 外側のシートグループキー → __inputs__[name] → __config__[name](真偽値リテラル TRUE/FALSE はこのチェインの前にリテラルとして解決される) |
データセル内の裸の識別子はソース列に解決されません。列を参照するには、作成者は必ず明示的な [Column] 形式を使う必要があります(MUST)。データセル内のショートハンド解決チェインは、output_file_pattern が {{ [Region] }}.xlsx であるシート内で {{ Region }} がそのアクティブグループの値を意図通りに読めるようにするために存在します。
リテラル
XTL 0.1 は以下をサポートします。
"text"
123
123.45
-123
文字列リテラル(ADR-0028 による)
" で囲まれた、対応のとれた組です。エスケープシーケンスはありません。バックスラッシュはそのまま透過します。0.x では文字列リテラル内に " を埋め込む規範的な方法はありません。値の中に " を含めたい作成者は、__config__ の作成者キーに保持し(セル内容には任意の文字を入れられます)、{{ __config__[key] }} で参照してください。
不整合または重複した引用符("a"b"、"a など)の挙動は実装定義です。ポータブルなテンプレートはリテラルごとにちょうど 1 組の対応した引用符を使ってください。
数値リテラル(ADR-0028 による)
10 進数で、負の符号として先頭に - を任意に置けます。許容される形:5、-5、3.14、-3.14、0。Unicode マイナス U+2212 は符号として認識されません(ADR-0009 の amendment による)。
非リテラル式に対する単項演算子は XTL 0.x ではサポートされません。 以下はすべて xl3/eval/unsupported-syntax を発生させます。
+5、+[col](単項プラス)--5、-(0 - 5)(二重否定)-[col]、-(expr)、-__config__[k](非リテラルに対する単項マイ ナス)
列の符号反転のワークアラウンド:(0 - [col]) または [col] * -1 と書きます。
演算子
算術 — +、-、*、/
両オペランドは有限数に強制変換できる必要があります(MUST)。強制変換規則は ADR-0023 によります。
| オペランド型 | 強制変換後の値 |
|---|---|
| Number(有限) | そのまま |
| Boolean | 1(TRUE)/ 0(FALSE) |
| 空(空値) | 0 |
| 有限な数値としてパース可能な文字列 | パースされた数値 |
| 数値としてパースできない文字列 | エラー xl3/eval/operand-coercion |
| Date | エラー |
| その他 | エラー |
文字列パースは ADR-0009 と ADR-0023 に従います。すなわち trim してから NaN を生まない Number()。カンマは桁区切りとして扱われ("1,234" は 1234 にパースされます)、リテラルでは指数表記なし、先頭の + もなしです。Unicode マイナス U+2212 は符号文字ではありません(ADR-0009 amendment)。
ADR-0064 により、文字列→数値の強制変換(リテラルパ ースとは別)は次の形を受け入れます。
| 形 | 受け入れ可? | 例 |
|---|---|---|
| 10 進整数 | はい | "42"、"-42" |
| 10 進小数 | はい | "3.14"、"-3.14" |
| 桁区切り | はい | "1,234"、"-1,234.56" |
| 指数表記 | はい | "1e5"、"-1.5e-3"、"1.5E10" |
16 進プレフィックス 0x/0X | いいえ — エラー xl3/eval/operand-coercion | "0x10" |
2 進プレフィックス 0b/0B | いいえ | "0b101" |
8 進プレフィックス 0o/0O | いいえ | "0o17" |
先頭 + | いいえ | "+5" |
Unicode マイナス U+2212 プレフィックス | いいえ | "−5" |
±Infinity を生じる | いいえ | "Infinity"、IEEE 754 オーバーフロー |
| 末尾の非数値文字 | いいえ | "5px"、"5 abc" |
| 複数行文字列 | いいえ | 内部に LF を含む文字列 |
リテラルパース(厳格)と文字列強制変換(寛容)の間の非対称性は意図的です。リテラルは作成者が記述するものですが、強制変換される文字列はデータ(CSV エクスポート、財務システム)から来るもので、そこでは指数や 16 進表記が自然に出現します。
{{ [price] * [quantity] }}
{{ [total] / 10 }}
{{ [a] + [b] }}
{{ [a] - [b] }}
例:
| 式 | 結果 |
|---|---|
1 + 2 | 3 |
"10" + 5 | 15 |
"1,234" + 1 | 1235 |
TRUE + 1 | 2 |
[empty-cell] + 5 | 5 |
"abc" + 5 | エラー |
ゼロ除算は Excel の #DIV/0! エラーセルを生成します(ADR-0025)。数値フォーマットの単一式セルは実際の Excel エラーセル(値 #DIV/0!)としてレンダリングされ、テキストフォーマットセル、混在テキストセル、または & 連結の内部では、その位置に文字列 "#DIV/0!" が置換されます。エラー値が同一セル式内の更なる算術演算子に流入する場合(例:(1/0) + 5)、有限数への強制変換に失敗し、上表に従い xl3/eval/operand-coercion を発生させます。
6 種類のソース側 Excel エラーセンチネル — #N/A、#VALUE!、#REF!、#NAME?、#NUM!、#NULL! — は ADR-0017 に従いソースから空値として読み込まれます。ADR-0053 により、これらは混在テキストおよび & 連結位置で "" を寄与し、数値/日付フォーマットの単一式セルでは xl3/cell/numfmt-coercion を発生させます。#DIV/0! は XTL 評価中にエンジン自体が生成する唯一のセンチネルで、上記の規則に従います。ソース側センチネルに対して可視の「欠損」マーカーを出したい作成者は、列参照を IFEMPTY([col], "missing") でラップしてください。
文字列連結 — &
各オペランドは正規文字列形式(比較と文字列強制変換を参照)でストリング化され、結果が連結されます。常に成功し、型エラーは発生しません。
{{ [item] & " (" & [size] & ")" }}
比較 — =、!=、>、<、>=、<=
IF() と @filter で使用します。比較と文字列強制変換のアルゴリズムに従います。型が混在する場合は正規文字列形式のコードポイント順にフォールスルーし、強制変換エラーは発生しません。
=
!=
>
<
>=
<=
比較と文字列強制変換
比較演算子(=、!=、>、<、>=、<=)と & 連結演算子は単一の強制変換モデルを共有します。IF() の条件と @filter ディレクティブは、ここで定義する比較アルゴリズムを使います。@sort も同じアルゴリズムを使います。
正規文字列形式
値の正規文字列形式は以下のとおりです。
-
空値(空値)は空文字列
""。 -
Boolean:
TRUEまたはFALSE(大文字)。 -
有限な数値:その値を一意に識別する最短 10 進表現。小数点として
.を用い、[1e-6, 1e21)の範囲では指数表記を使いません。整数は末尾の小数点を省略します。ECMA-262 §6.1.6.1.13 に一致します。 -
文字列:その文字列自体。
-
日付:時刻成分がちょうど真夜中(
00:00:00)のときはYYYY-MM-DD、それ以外はYYYY-MM-DDTHH:mm:ss(ADR-0017 で定義。以前は ADR-0009 から繰り延べ)。日付要素は UTC で読まれる必要があります(MUST)。Excel のセルはタイムゾーンを持たないシリアル日付を格納し、ExcelJS などのライブラリはこれを UTC アンカーの
Dateオブジェクトとして返します。ローカルタイムゾーンのアクセサ(getFullYear、getMonth、getDate)を使うと、UTC ではないホスト上で 1 日ずれる現象が発生します。タイムゾーン考慮の日付(例:「ソウルの今日」のファイル名トークン)が必要な ホストは、レンダラの外側で計算し、__inputs__または__config__を通して渡してください。
非有限な数値(NaN、Infinity、-Infinity)は仕様準拠の演算からは生じてはなりません(MUST NOT)。出現した場合は "" にストリング化されます。
比較アルゴリズム
比較演算子は以下の順に適用します。
- 両オペランドが空であれば等しい。
=は真、!=は偽、>と<は偽、>=と<=は真。 - ちょうど一方のオペランドが空であれば、
=は偽、!=は真。順序付けでは、空値は任意の非空値より小さい。 - 両オペランドが数値であるか、両方が「trim してから
NaNを生まないNumber()」を経て有限数にパースされる文字列であれば、数値として比較します。数値比較は IEEE 754 の等価性を使います。0.1 + 0.2は0.3と等しくありません。許容差が必要なテンプレートはROUND()で明示的に丸める必要があります(MUST)。 - 両オペランドが Boolean なら、
falseをtrueの前に置く順序で値として比較します。 - 両オペランドが日付であれば、内部タイムスタンプで比較します。これは、一方が真夜中のみの
YYYY-MM-DDで他方が日時の場合をカバーします(そうでなければ異なる正規文字列として比較されてしまう)。 - それ以外の場合、正規文字列形式を Unicode コードポイント順で比較します。ロケール対応の照合は適用されません。Unicode 正規化も適用されません(ADR-0030)。NFC
한(U+D55C)と NFD한(U+1112 U+1161 U+11AB)は同じに表示されますが、別の文字列として比較されます。混在形式のデータを持つ作成者は、上流で正規化してください。
& 連結
& は各オペランドを正規文字列形式にストリング化し、順に結合します。& の結果は常に文字列です。
関数
関数名は大文字小文字を区別しません。仕様では大文字で書きます。
ユーザ向けの各関数は規範的なアリティを持ちます(ADR-0024)。引数の数が誤っている呼び出しは、オペランド評価の前に、パース/正規化時点で xl3/eval/arity-mismatch を発生させます。
| 関数 | 引数 | 備考 |
|---|---|---|
IF | 3 | 条件, 真値, 偽値 |
IFEMPTY | 2 | 値, フォールバック(別名:IFBLANK) |
ROUND | 2 | 値, 桁数 |
ABS | 1 | 値 |
TEXT | 2 | 値, フォーマット |
ROW | 0 | 現在のデータブロック内の行インデックス |
TODAY | 0 | UTC 日付 |
YEAR | 1 | 日付の 4 桁年(UTC) — ADR-0019 amendment |
MONTH | 1 | 日付の月 1-12(UTC) — ADR-0019 amendment |
DAY | 1 | 日付の日 1-31(UTC) — ADR-0019 amendment |
EOMONTH | 2 | ある日付から N か月後の月の最終日(UTC 真夜中) — ADR-0019 amendment |
EDATE | 2 | ある日付から N か月後の日付(同日にクランプ、UTC 真夜中) — ADR-0019 amendment |
DATEDIF | 3 | 2 つの日付間の完全な "Y"/"M"/"D" 単位の整数カウント(start > end のときは負) — ADR-0019 amendment |
HYPERLINK | 2 | url, ラベル — クリック可能なセルを生成 — ADR-0039 |
UPPER | 1 | 文字列中の英字を大文字化 — ADR-0044 |
LOWER | 1 | 文字列中の英字を小文字化 — ADR-0044 |
TRIM | 1 | 先頭・末尾の空白を除去(内部は保持) — ADR-0044 |
IFERROR | 2 | 値, フォールバック — 値がエラーセルマーカーのときフォールバックを返す — ADR-0044 |
IFS | 偶数 ≥ 2 | (条件, 値) のペア。最初に真の枝を返す。どれも真でなければ xl3/eval/no-match — ADR-0044 |
DATE | 3 | 年, 1-based の月, 日 — UTC 真夜中 — ADR-0044 |
ISBLANK | 1 | 値が ADR-0007 に従い空のとき真。IFEMPTY 述語の別名 — ADR-0047 |
XLOOKUP | 3 または 4 | 値, lookup-array, return-array, [フォールバック] |
SUM | 1 | 列参照 |
AVERAGE(別名 AVG) | 1 | 列参照 |
MIN | 1 | 列参照 |
MAX | 1 | 列参照 |
COUNT | 0 または 1 | 0 = ブロック行数;1 = 列の非空カウント |
CONCAT | 1+ | 可変長。& の代替 |
IF
{{ IF([quantity] > 100, "bulk", "normal") }}
条件が真値(truthy)であるとき第 2 引数を返し、そうでなければ第 3 引数を返します。
値が真値(truthy)であるのは、次のいずれにも該当しない場合です。
- Boolean の
false。 - 数値
0。 - 空値に従い空である値 — 欠落、
""、または空白のみの文字列。
文字列 "0" や "false" に対する特別な扱いはありません。非空白の内容を含む文字列は常に真値(truthy)で、文字列型のフラグ値 "0" や "false" であっても同様です。そうしたフラグを解釈する必要があるテンプレートは、明示的に比較する必要があります(MUST)。例:IF([flag] = "1", …)。
比較式は Boolean に評価され、比較が成立するときに真値(truthy)となります。
IFEMPTY
{{ IFEMPTY([memo], "-") }}
第 1 引数が 空値 に従い空のとき第 2 引数を返します。それ以外の場合は第 1 引数を返します。
XLOOKUP
{{ XLOOKUP([Account], Customers[Account], Customers[Name]) }}
{{ XLOOKUP([Account], Customers[Account], Customers[Name], "(unknown)") }}
lookup_value を lookup_array の中から探し、対応する return_array の値を返します。配列はソース接頭辞付きのブラケット参照(例:Customers[Account])でなければならず(MUST)、同一のソースから来る必要があります(MUST)。
関数はソースの行をワークブック順に走査し、lookup_array 列が lookup_value と比較アルゴリズム上で等しい最初の行を返します。マッチがない場合:
- 第 4 引数が指定されていればそれを返す。
- そうでなければエラー。
XTL 0.1 は完全一致のみをサポートします — ワイルドカード、近似一致、逆方向検索はありません。
ADR-0060 により、lookup_value(第 1 引数)とオプションの fallback(第 4 引数)は完全な XTL 式です。リテラル、裸のブラケット、ソース接頭辞付きブラケット、関数呼び出し、または合成式のいずれでもよい(MAY)。これらの位置の Source[Column] 参照はアクティブソース規則(ADR-0012)の対象となります。すなわち、Source が周囲のブロックのアクティブソースである場合のみ現在行に解決され、そうでなけれ ば xl3/source/row-cross-block を発生させます。配列引数の制約(同一ソース、裸のブラケット禁止)は lookup_array と return_array にのみ適用されます。
集計関数
集計はレンダリング中の現在の行セットに対して動作します。
{{ SUM([total]) }}
{{ COUNT() }}
{{ COUNT([customer]) }}
{{ AVERAGE([price]) }}
{{ MIN([date]) }}
{{ MAX([date]) }}
COUNT() は行数をカウントします。COUNT([field]) は [field] の値が空値に従い非空である行をカウントします。
ADR-0059 により、SUM、AVERAGE(および別名 AVG)、MIN、MAX、および COUNT の 1 引数形式に渡す単一引数は、[Column] または Source[Column] の形の列参照でなければなりません(MUST)。それ以外の形(リテラル、式、関数呼び出し)は xl3/eval/bad-aggregate-arg を発生させます。行ごとの計算済み集計が必要な作成者は、上流でヘルパー列を追加するか、行ごとの値を別のセルで計算してください。
数値関数
{{ ROUND([amount], 0) }}
{{ ABS([delta]) }}
ROUND(value, places) は指定の小数点桁数に丸めます。丸めは half-away-from-zero(ゼロから遠ざかる方向)で、Excel の ROUND() と一致します(例:ROUND(2.5, 0) は 3、ROUND(-2.5, 0) は -3)。
テキスト書式
{{ TEXT([date], "YYYY-MM-DD") }}
{{ TEXT([amount], "#,##0") }}
以下のサポート対象フォーマットについて、TEXT() は文字列を返します。出力を数値や日付値のままにしたい場合は、テンプレートセルの数値/日付フォーマットを使ってください。
XTL 0.1 は以下の最小限の TEXT() フォーマットサブセットを定義します。
| 種別 | トークン/フォーマット | 意味 |
|---|---|---|
| 日付/時刻 | YYYY, YY, MM, DD, dd, HH, hh, mm, ss | ゼロパディングされたカレンダーフィールド(YYYY と YY を除く)。DD と dd はいずれも日。 |
| 数値 | 0 | 桁区切りなしの丸めた整数。 |
| 数値 | #,##0 | , の桁区切り付きの丸めた整数。 |
| 数値 | 0.00 | 桁区切りなしの 2 桁固定小数。 |
| 数値 | #,##0.00 | , の桁区切り付きの 2 桁固定小数。 |
数値の TEXT() の丸めは ROUND() と同じ half-away-from-zero の規則を使います。
この表の外のフォーマットは XTL 0.1 における拡張です。実装は追加のフォーマットを受け入れてよい(MAY)が、その正確な出力は実装定義であり、コア適合性の対象外です。ポータブルなテンプレートは上表のみを使う必要があります(MUST)。
行・日付関数
{{ ROW() }}
{{ TODAY() }}
{{ TEXT(TODAY(), "YYYY-MM-DD") }}
ROW() は現在のリピートブロック内の 1-based 行インデックスを返します。リピートブロックの外で ROW() を呼ぶのはエラーです。TODAY() はレンダリング時の UTC 日付を返します。実装はホストランタイムのローカルタイムゾーンを使ってはなりません(MUST NOT)。ロケール固有の日付が必要なテンプレートは、ソースワークブックで計算するか、__config__ を通じて作成者定義値として渡してください。
ディレクティブ
ディレク ティブはテンプレート式として、通常データブロックの直上の行に書かれます。
{{ @filter [Status] = "Open" }}
{{ @filter [Customer] in __lists__[IncludedCustomers] }}
{{ @filter [Category] !in __lists__[ExcludedCategories] }}
{{ @sort [total] desc }}
{{ @group [Region], [Customer] }}
{{ @top 10 }}
{{ @repeat right 3 }}
{{ @source Renewals }}
{{ @join Customers on Customers[Account] = Renewals[Account] }}
{{ @block A:D }}
ディレクティブ名とソート方向は大文字小文字を区別しません。
@block — 明示的なデータブロック宣言
ADR-0067 により、@block は作成者がデータブロックの geometry を明示的に宣言できるようにします。3 つの形式を認識します。
@block — bare。列範囲は {{...}} marker から自動検出
@block <col-range> — 明示的な列範囲。例: A:D
@block <full-rect> — 明示的な行 × 列矩形。例: A2:D7
@block directive セルは、ブロックの最初の行より厳密に上の行に置かれます。引数なしの場合、ブロックの列範囲は directive の下にある {{ ... }} marker セルの bounding box です(ADR-0066 の列スコープ検出)。A:D のような col-range 引数では、列範囲が明示され、行範囲は自動検出されます。A2:D7 のような完全矩形では、行範囲と列範囲の両方が明示されます。矩形は少なくとも 1 つの marker cell を含む必要があり(MUST)、そうでなければ xl3/block/empty-table が発生します。
同一シート上の 2 つの @block 矩形は重なってはなりません(MUST NOT)。任意の行 × 列交差は xl3/block/overlap を発生させます。
ブロック検出モード(ADR-0068、strict): シートは zero 個の @block directive を持つ(implicit mode — ADR-0066 の single-block cluster detection が適用され、複数の disconnected cluster は xl3/expression/bracket-outside-block を発生させる)か、1 個以上の @block directive を持つ(explicit mode — すべての [Column] marker cells はいずれかの @block 矩形内に存在しなければならず(MUST)、orphan marker は同じエラーコードを発生させる)かのどちらかです。
multi-block シートでの directive スコープ(ADR-0069): その他すべての directive — @filter、@sort、@top、@source、@join、@group、@repeat — は proximity によって特定のブロックに attach されます。
directive
Dが(r_D, c_D)にあるとする。これは、(1)r_D < B.startRow、(2)B.colStart ≤ c_D ≤ B.colEnd、(3) (1) と (2) を満たすブロックの中でB.startRow - r_Dが最小、を満たすデータブロックBに attach される。(1) と (2) を満たすブロックがない場合、その directive はxl3/directive/orphanを発生させる。
この規則は single-block シートでは正しく退化します。候補が 1 つしかないため、closest-block-below check は自明です。
ブロック内の ROW() は、そのブロックの iteration index(レコードごとに 1-based)を返します。どのブロックにも属さない ROW() セルは xl3/expression/row-outside-block を発生させます。
Filter
@filter [field] operator value
演算子:
=
!=
>
<
>=
<=
in
!in
in と !in は __lists__[<name>] の形のリスト参照を要求します(ADR-0011)。ここで <name> は予約シート __lists__ 内の列ヘッダです。レガシーの _<name> リストシート形式は廃止されました。
複数の @filter ディレクティブは AND で合成されます。 行がブロックを通過するのは、すべての @filter 述語が満たされる場合のみです。XTL 0.1 に OR の形はありません。論理和が必要なテンプレートは、__lists__[…] メンバーシップフィルタで代替を合成するか、上流でソースを事前フィルタしてください。
{{ @filter [Region] = "Seoul" }}
{{ @filter [Amount] > 10000 }}
行は両方の条件を満たす場合のみ通過します。
Sort
@sort [field] asc
@sort [field] desc
方向を省略した場合は asc が使われます。
@sort は**安定(stable)**です。ソートキーが等しい行は、ソース順序を保ちます。複数の @sort ディレクティブがある場合、最初のディレクティブが主ソートキーで、以降のディレクティブは出現順にタイブレーカーとなります。ソース順序は最後のタイブレーカーです(Excel の「並べ替え … 次に並べ替え」や SQL の ORDER BY a, b と一致)。
Top
@top 10
フィルタとソートの後で先頭 N 行を保持します。ADR-0055 により、N は正の整数(≥ 1)でなければなりません(MUST)。@top 0、@top -5、@top 05(先頭ゼロ)はパースエラーで xl3/directive/invalid-syntax を発生させます。
Repeat Right
@repeat right
@repeat right 3
検出されたデータブロックを水平方向に繰り返します。オプションの数値は繰り返し 1 件あたりの列スパンです。省略時の列スパンは 1 です。ADR-0055 により、列スパンは正の整数(≥ 1)でなければなりません(MUST)。@repeat right 0 と @repeat right -3 は xl3/directive/invalid-syntax を発生させます。
Source
@source <SourceName>
周囲のデータブロックを、__sources__ で宣言された名前付きソースにスコープします(ADR-0012)。ブロック内では、ブラケットショートハンド [Column] はアクティブソースの行に解決され、Source[Column] 上の集計は従来通り動作します。@source がなければ、アクティブソースは __config__ で構成された既定の source_sheet です。
明示的な @source default は合法で、ディレクティブを省略するのと等価です(ADR-0065)。ソース名引数は大文字小文字を区別します。@source DEFAULT は xl3/source/undeclared を発生させます。__sources__ の行でその名前を宣言したものがないためです。
未宣言ソースの参照はエラーです。ソースのヘッダに宣言されていない列の参照はエラーです(xl3/source/unknown-column)。空値への暗黙のフォールスルーはタイプミスを覆い隠します。
Join
@join <JoinedSource> on <JoinedSource>[<key>] = <PrimarySource>[<key>]
@source ブロックの各プライマリ行を、<JoinedSource> の最初にマッチした行とペアにします(ADR-0014、内部結合セマンティクス、最初のマッチ)。マッチしないプライマリ行はドロップされます。ブロック内では、<PrimarySource>[Column] と裸の [Column] はプライマリ行に解決され、<JoinedSource>[Column] はペアになった結合行に解決されます。複数の @join 句、左結合セマンティクス、複数行マッチは XTL 0.1 の範囲外です。
on 句の両辺はソー ス接頭辞付きのブラケット参照でなければなりません(MUST)。一方が <JoinedSource>、他方が <PrimarySource> を指名する必要があります(MUST)。いずれかのソースが __sources__ で未宣言、または on 句が不正な場合はエラーです。
Group + Subtotal
@group [Key1], [Key2], …, [KeyN]
@group は、アクティブな行セットを N レベルのネストされたグループに分割し、単一のデータブロック内で @subtotal 行を交互に出力するためのものです(ADR-0038)。グループの同定には ADR-0009 の正規文字列等価ルールを使い、グループ順は @filter と @sort が適用された後の出現順です(@group 自体は並べ替えを行いません)。
データブロックは最大 1 つの @group を含むことができます(MAY)。キーリストのない @group は xl3/group/missing-key を発生させます。@group は @repeat right と両立しません(xl3/directive/invalid-syntax)。
@subtotal 行は、1 つ以上の {{ @subtotal <aggregate> }} 式を含みます。各小計行は 1 つのグループネスティングレベルにバインドされます。ソース順で最初の @subtotal 行は最内側のキー([KeyN])にバインドされ、次の行は [KeyN-1] にバインドされ、外側へと続きます。最外側の @subtotal はデータブロックの末尾で 1 度発火します(「最外側 subtotal による総合計」パターン)。
サポートする集計本体 — それ以外は xl3/subtotal/bad-aggregate を発生させます。
SUM(<column-ref>)COUNT()またはCOUNT(<column-ref>)AVERAGE(<column-ref>)MIN(<column-ref>)MAX(<column-ref>)
合成式(SUM([A]) - SUM([B])、IF(...) など)は繰り延べです。集計内の列参照は他の箇所と同じ [Column] / Source[Column] 形式に従います。ADR-0038 § "Aggregate scoping" のスコープ規則が適用されます — 集計はブロック全体ではなく、現在のグループの行セットに対して動作します。
ADR-0058 により、@subtotal 行は異なるセルに任意の数の {{ @subtotal <aggregate> }} 式を含むことができます(MAY)。これらはすべて、行の単一のネスティングレベルバインディング(行順から推測されるレベル)を共有し、各発火時に同じグループ行セットに対して評価されます。1 つの小計行に集計種類(SUM + COUNT + AVERAGE)と列参照を混在させることが許容されます。
@subtotal 行は、リテラルテキストセル、静的数式、および現在行の列を参照しない他の {{ ... }} 式も持つことができます(MAY)。グループ境界では「現在行」が存在しないためです。集計の外で現在行の列を参照すると xl3/expression/unknown-name クラスのエラーが発生します。
空のグループ — すべてのデータ行が空(ADR-0007)— はスキップされます。
{{ @sort [Region] }}
{{ @sort [Customer] }}
{{ @group [Region], [Customer] }}
{{ [Region] }} | {{ [Customer] }} | {{ [Amount] }}
"Customer subtotal" | | {{ @subtotal SUM([Amount]) }}
"Region subtotal" | | {{ @subtotal SUM([Amount]) }}
エラー:
xl3/group/missing-key— キーリストのない@group。xl3/subtotal/outside-group—@groupのないブロック内の@subtotalセル、または@groupのキー数より多い@subtotal行。xl3/subtotal/bad-aggregate—@subtotal本体がSUM、COUNT、AVERAGE、MIN、MAXのいずれでもないか、引数が許容形式の列参照ではない。
グループキー
Excel のシート名には [ や ] を含められないので、シート名は裸のグループキーを使います。
{{ Customer }}
ファイルパターンは裸のグループキーまたはブラケット付きソース列のいずれかを使うことができます。
{{ Customer }}_report.xlsx
{{ [Customer] }}_report.xlsx
{{ TEXT(TODAY(), "YYYY-MM-DD") }}_report.xlsx