XTL 評価モデル
この日本語訳は読みやすさのための補助資料です。仕様の正典は英語原文で、規範的な解釈の差異が生じた場合は英語版が優先します。
本ドキュメントは、XTL 実装が入力を読み取り、出力を生成する方法を定義します。
入力と出力
XTL 変換は次を入力にとります。
template.xlsx
data.xlsx
そして 1 つ以上の .xlsx 出力ファイルを生成します。
テンプレートワークブックは、出力ワークブックの形、テンプレート式、グループ化規則、ディレクティブ、および設定を定義します。ソースワークブックは表形式データを提供します。
予約シート
xl3 は 4 つの予約シート名を定義します。__<name>__ というダンダーで囲まれたパターンに一致するシート名は、エンジン利用のために予約されています。作成者はこの形のシートを作成してはなりません(MUST NOT)。それ以外のすべてはテンプレートコンテンツです。
| シート | 用途 |
|---|---|
__config__ | 単一の設定オブジェクト — エンジンのメタデータ + 作成者定義の値 |
__inputs__ | 実行時入力宣言(コレクション。Inputs 参照) |
__sources__ | 名前付き外部データソース宣言(コレクション。External Data Sources、ADR-0012) |
__lists__ | 作成者定義のメンバーシップリスト(コレクション。List Sheets 参照) |
セル式から予約シートの内容を参照するには Excel の構造化参照形式 __sheet__[key] を使います。これは将来の ADR でマルチソース列にも用いら れる同じ形式です。レガシーな _<name> 参照構文はこのバージョンで廃止されています。
テンプレート設定
__config__ という名前の隠しシートは、メタデータと作成者定義の値を提供できます(MAY)。列 A がキー、列 B が値を保持します。
| キー | 意味 | 例 |
|---|---|---|
name | テンプレート表示名 | Order summary |
description | 自由テキスト | Monthly order summary |
source_sheet | ソースシート名、または * で終わる接頭辞パターン | Orders、Data_* |
source_table | ソーステーブルセレクタ。最初に選択された行が列名を含み、その下の行がデータです。 | 1、A1:D、B5:H200 |
output_file_pattern | 出力ファイル名テンプレート | {{ __config__[customer] }}_report.xlsx |
match_pattern | バッチマッチングパターン | Orders* |
| その他任意のキー | 作成者定義値 | title = Q2 Sales |
source_table は唯一のソーステーブルセレクタです。
作成者定義の値は、上記のシステムテーブルに列挙されていない任意のキーを使います。セルからは {{ __config__[key] }} で参照されます。例えば、行 title = Q2 Sales は {{ __config__[title] }} として参照されます。作成者はシステムキー名を作成者定義値に再利用してはなりません(MUST NOT)。
ADR-0056 に従い、__config__[key] の読み出し形式は、key がシステムスロットか作成者定義スロットかに関わらず、セル値に解決されます。{{ __config__[name] }}、{{ __config__[output_file_pattern] }} などは正当な読み出しです。書き込み側の制約(作成者がシステムキー名で行を宣言できない)は変更ありません。未知のキーを読み出すと xl3/expression/unknown-name が発生します。
実行ごとの値が必要なテンプレートは、代わりに __inputs__ シートを使います(Inputs 参照)。
外部データソース
テンプレートは、予約シート __sources__ を提供することで、デフォルト以外の名前付きデータソースを宣言できます(MAY)。行 1 がヘッダーで、それ以降の各行が 1 つのソースを宣言します。
| 列 | 必須 | 意味 |
|---|---|---|
name | はい | ソース名。英字、数字、アンダースコアのみ。__ で始まってはならず(MUST NOT)、default であってもなりません(MUST NOT。暗黙ソースに予約) 。 |
sheet | はい | データワークブック内のソースワークシート名、または * で終わる接頭辞パターン。 |
table | いいえ | そのシートのソーステーブルセレクタ。デフォルトは 1。__config__ の source_table と同じ構文。 |
description | いいえ | 自由形式のメモ。 |
実装は列をヘッダーテキストで(大文字小文字を区別せずに)識別する必要があります(MUST)。
暗黙の default ソース — __config__ の source_sheet / source_table 行で宣言される — は常に default と名付けられます。__sources__ で再宣言することはできません。
セル参照
[Column] は引き続き「アクティブソースの現在行の列」を意味します。Source[Column] は名前付きソースの構造化参照形式です。
{{ [Account] }} アクティブソースの現在行
{{ Customers[Account] }} Customers の現在行(アクティブなときのみ)
{{ SUM(Renewals[Amount]) }} Renewals の全行集合に対する集計
行レベルの Source[Column] は、Source が囲むデータブロックのアクティブソースである場合にのみ有効です。集計関数の内部では、Source[Column] は常にアクティブなブロックとは独立に Source の全行集合に対して動作します。
@source ディレクティブ
データブロックは、その反復を名前付きソースにスコープできます(MAY)。
{{ @source Customers }}
{{ @filter [Region] = "Seoul" }}
{{ [Account] }}
{{ [Region] }}
上のデータブロックは、明示的な @repeat ディレクティブなしでデフォルトで垂直に展開します — ソース行 1 行あたり 1 つのレンダー行(Directives 参照)。
@source がない場合、アクティブソースは default です。@source は、同じブロックの @filter / @sort / @top ディレクティブの前に現れる必要があります(MUST。これらが動作する行集合を決定するため)。
未宣言のソースを参照すること — @source <Unknown> 経由でも Unknown[Column] 経由でも — はエラーです。
@join ディレクティブ
データブロックは、@source の直後に 1 つの @join ディレクティブを追加して、各プライマリソース行を 2 番目のソースの行とペアにすることができます(MAY)。
{{ @source Renewals }}
{{ @join Customers on Customers[Account] = Renewals[Account] }}
{{ [Account] }} | {{ Customers[Name] }} | {{ [Amount] }}
プライマリ行ごとに、エンジンは(Comparison Algorithm に従って)最初に一致する結合行を見つけ、そのペアをレンダリングします。「最初」は結合ソースの自然な行順 — その source_table 範囲を上から下へ — で定義されます。これは規範的です:複数の結合行が等しい結合キーを持つとき、2 つの実装は同じペア行を選ぶ必要があります(MUST)。
一致が見つからない場合、プライマリ行はドロップされます(内部結合のセマンティクス)。
ブロック内では、[Column] と <PrimarySource>[Column] はプライマリ行に解決され、<JoinedSource>[Column] はペアの結合行に解決されます。行レベルでの他のソースへの参照は、引き続きエラーです。
複数の @join ディレクティブ、左外部結合のセマンティクス、複数行マッチは XTL 0.1 のスコープ外です。
Inputs
テンプレートは、予約シート __inputs__ を提供することで、実行時入力を宣言できます(MAY)。最初の行がヘッダーで、それ以降の各行が 1 つの入力を宣言します。
| 列 | 必須 | 意味 |
|---|---|---|
name | はい | 入力名。英字、数字、アンダースコアのみで構成されている必要があります。 |
type | はい | text、number、date、select のいずれか。 |
default | いいえ | 非空であれば、ホストがその入力を省略したときに使われます。デフォルト値は入力の type によってパースされます。 |
label | いいえ | ユーザ向けのプロンプトテキスト。ホストはこれをフォームラベルとして用いるべきです(SHOULD)。 |
description | いいえ | オプションの長めのヘルプ。 |
options | いいえ | type = select のときに必須。パイプ区切りの許容値、例:Seoul|Busan|Daegu。 |
実装は列をヘッダーテキストで(大文字小文字を区別せずに)識別する必要があります(MUST)。上記以外の列は予約されており、無視する必要があります(MUST)。
行に default がない入力は required(必須) です。ホストはすべての必須入力を供給する必要があり(MUST)、省略するとエラーです。
解決済みの入力値は、セルからは {{ __inputs__[name] }} で参照されます。例えば、name = month で宣言された入力は {{ __inputs__[month] }} として参照されます。__inputs__[name] は解決済み + 強制変換済みの値に解決されます。テンプレート内部から入力の label、default、type を読む仕様上の形式はありません(ホストは readTemplateInputs() API を使います)。
入力名は、__config__ の非システム行として宣言された作成者定義値と衝突してはなりません(MUST NOT)。これはパース時のエラーです。
ADR-0062 に従い、入力は default セルが ADR-0050 評価後に ADR-0007 の意味で空値を生成するときに required(必須) となります。「空セル」、default = ""、default = " "、default = {{ "" }} の各形は、すべて「required」に畳まれます。
ADR-0063 に従い、options セルは評価後に | で分割されます。各要素は Unicode 空白でトリムされ、空要素はドロップされます。options = "Seoul | Busan" は ["Seoul", "Busan"] を生成します。options = "a||b" は ["a", "b"] を生成します。options = "||" は xl3/inputs/missing-options を発生させます。重複オプションは保持されます。ホスト供給の select 値は、結果配列に対して大文字小文字を区別してマッチします。
入力はホスト供給値から強制変換されます。
text— ホスト文字列をそのまま透過します。非文字列のホスト値は正規文字列形式(Comparison and String Coercion 参照)でストリング化します。number— 「trim してからNaNを生まないNumber()」でパースします。失敗はエラーです。date— 日付フォーマットの単一式セルと同じ規則で強制変換します。失敗はエラーです。select— ホスト値は、正規文字列形式の正規化後に、宣言されたoptionsのいずれかと等しい必要があります(MUST)。失敗はエラーです。
強制変換された入力値は、他の値と同じく IF()、@filter、&、比較、TEXT() に参加します。
default / label / description / options におけるテンプレート評価
ADR-0050 に従い、default、label、description、options 列のセルは XTL テンプレート — 連続テキストと 0 個以上の {{ ... }} ブロック — であり、入力読み込み時(任意のソース行がロードされる前)に評価されます。評価コンテキストは意図的に制約されています。
利用可能なバインディング:
__config__[key]—__config__シート(__inputs__の前にパースされる)からの作成者定義値。- 純スカラー関数:
TODAY、DATE、IF、IFEMPTY、IFS、IFERROR、UPPER、LOWER、TRIM、TEXT、YEAR、MONTH、DAY、EOMONTH、EDATE、DATEDIF、ROUND、ABS。
禁止されたバインディング(安定エラーコードを発生させます):
- 裸の
[Column]またはSource[Column]参照 — 入力 読み込み時にはソース行コンテキストがまだありません。エラー:xl3/inputs/forward-reference。 __sources__[…]または__inputs__[name]— ソースはロードされていません。入力行は独立した宣言です。エラー:xl3/inputs/forward-reference。ROW()、SUM、COUNT、AVERAGE、MIN、MAX、XLOOKUP— レンダー時またはソースデータに依存します。エラー:xl3/inputs/runtime-only-fn。
評価後の正規文字列形式(ADR-0009 参照)が、ホスト UI へ InputSpec.default / InputSpec.label / InputSpec.description として戻されるものです。options については、評価された文字列がさらに | で分割されて配列を生成します。
default については、評価された文字列はその後、入力の宣言された type に従って上記の規則で強制変換されます。したがって type = date の default = {{ TODAY() }} は、強制変換後のデフォルトとしてレンダー時の ISO 日付を生成します。
ソースデータモデル
ソースデータモデルは行の順序付きリストです。各行は、ソース列名からセル値へのマッピングです。
source_sheet はワークシートを選択します。省略時は最初のワークシートが使われます。source_sheet が * で終わる場合、それ は接頭辞パターンです。実装は、ワークブック順で、* の前の接頭辞で始まる名前を持つ最初のワークシートを選択する必要があります(MUST)。一致するワークシートがない場合はエラーです。シート名の完全一致は接頭辞マッチングより優先します。
source_table は選択されたワークシート内で解釈されます。
| 形 | 意味 |
|---|---|
N | 行 N がソース列名を含みます。ソース列は、最初の非空セルから最後の非空セルまでの非空セルです。行 N の下からワークシートの使用済み行末までがデータ行です。 |
A1:D | セル A1:D1 がソース列名を含みます。その下からワークシートの使用済み行末までがデータ行です。 |
A1:D200 | セル A1:D1 がソース列名を含みます。列 A:D の行 2:200 がデータ行です。 |
source_table が省略された場合、デフォルトは 1 です。
N は 1 始まりの正の整数である必要があります(MUST)。範囲形式は、左列、最初の行、右列、およびオプションの終了行を持つ絶対 Excel A1 座標を使用する必要があります(MUST)。左列は右列の右にあってはなりません(MUST NOT)。オプションの終了行は最初の行の上にあってはなりません(MUST NOT)。
範囲形式が最初の行と等しい終了行を含む場合(例:A1:D1)、ソーステーブルには列名のみが含まれデータ行は 0 となります。これは正当です。
ソーステーブルの列名セルは、トリム前にソースデータセルと同じ有効テキスト/値抽出を使います。
列名規則:
- ソース列名セルの値は文字列に変換され、トリムされます。
- ソース列名は大文字小文字を区別します。
- リッチテキストのソース列名セルは、テキストランを連結して読み取られます。
- 数式のソース列名セルはキャッシュされた数式結果を使います。キャッシュされた結果が利用できない場合はエラーです。
- 選択されたソーステーブル内の空の列名はエラーです。
- 重複するソース列名はエラーです。
- 空のデータ行はスキップされます。
- 水平結合されたヘッダーセルは、結合マスタの列インデックスで 1 つの列を構成します(ADR-0033 に従う)。マスタとは別の列にある同じ行のスレーブセルは透過的です:列を構成せず、名前重複エラーを発生させません。ヘッダー行内の垂直結合は、マスタのテキストをスレーブの列でそのまま読みます。選択範囲が結合のスレーブセルのみを含む(ウィンドウ内にマスタがない)場合はエラーです(
xl3/source/missing-header)。結合マスタを含むよう範囲を広げてください。 - ヘッダーセルテキスト内の改行(CRLF、CR、または LF — Alt+Enter で書かれたものを含む)は、ADR-0041 amendment に従い、読み込み時に単一スペース(U+0020)に正規化されます。連続した複数の改行は 1 つのスペースに畳まれます。スペース畳み込み形式が列名であり、テンプレートはその同じスペース形式(
{{ [単位: 원] }})で参照します。トリムとトリム後の空検出(規則 5)は改行正規化の後に適用されます。ヘッダーの正規化はデータ行とは非対称です。データ行では、ADR-0041 の原スコープに従って LF はそのまま保持されます。
データ行(ヘッダー行の下の行)における結合セルは、ADR-0035 により別の規則に従います:結合スレーブの値は結合マスタの値です。N データ行にまたがる垂直結合は N データ行を生成し、それぞれその列でマスタの値を共有します。データ行の水平結合は、すべてのスレーブ列にその行でのマスタの値を与えます。空データ行のスキップは、結合のブロードキャスト後に評価されます。垂直結合を 1 つの論理レコードとして扱いたい作成者は、ソースデータ領域の結合を解除すべきです(SHOULD)。
行番号ショートハンド(source_table = N)の場合、最初と最後の非空列名セルの間のギャップは、したがってソース列スパンの推定後にエラーとなります。
空値
値は、欠落している場合 — ソース列がこの行に存在しない、またはセルが空白 — か、その内容がすべて Unicode 空白である文字列の場合に、空 です。
数値(0 を含む)は決して空ではありません。Boolean(false を含む)は決して空ではありません。日付は決して空ではありません。非空文字列は決して空ではありません。キャッシュ結果が空文字列である数式は、この規則により空です。
Excel エラーセル(#N/A、#VALUE!、#DIV/0!、#REF!、#NAME?、#NUM!、#NULL!)— 静的でも数式のキャッシュ結果として運ばれてきたものでも — もこの規則により空です(ADR-0017)。実装はそれらに出会ったときに警告を発しても構いません(MAY)。警告は出力セマンティクスを変更してはなりません(MUST NOT)。
空述語は、仕様が空値に言及するすべての場所を統括します。
IFEMPTY(value, fallback)はvalueが空のときfallbackを返します。COUNT([field])は[field]値が非空である行をカウントします。- ソーステーブルの列スパン内のすべてのセルが空であるとき、ソース行は空です。空のデータ行はグループ化とレンダリングの前にスキップされます。
- リストシートのエントリは、シートの最初の列から空セルを落として読まれます。
- 空であるソース行値は
@filter [field] in __lists__[name]に決してマッチしません。同じ値は常に@filter [field] !in __lists__[name]にマッチします。
List Sheets
テンプレートは、予約シート __lists__ を提供することで、名前付きメンバーシップリストを宣言できます(MAY)。行 1 がヘッダーで、各ヘッダーセルは 1 つのリストの名前です。行 1 の下では、各列がそのリストの値を保持し ます。
__lists__:
| fruits | allowed_status | excluded_regions |
|--------|----------------|------------------|
| apple | open | test |
| banana | pending | internal |
| cherry | reviewing | |
__lists__ シート:
- テンプレート内では可視、非表示、または超非表示のいずれでもよい(MAY)。
- 出力ワークブックからは削除する必要があります(MUST)。
- 各セルは Comparison and String Coercion に従い正規文字列形式に変換され、Unicode 空白でトリムされます。トリム後に空となるセル(Empty Values に従う)はスキップされます。
- 各列内の順序は保持されます。重複エントリは削除されません。
リストはフィルターディレクティブから参照します。
{{ @filter [Fruit] in __lists__[fruits] }}
{{ @filter [Status] !in __lists__[allowed_status] }}
__lists__[name] はリスト配列です。@filter ... in および @filter ... !in の内部でのみ有効です。それ以外で使用すると、ADR-0057 に従い xl3/lists/invalid-use が発生します。これはセル式内のリスト参照、=/!= などのオペランド、関数引数、@sort/@top 引数を網羅します。
__lists__ で宣言されていないリスト名を参照する(または __lists__ シートが存在しないのに __lists__[name] を参照する)と、xl3/lists/missing-reference が発生します。
レンダーフェーズ
実装はこの概念的順序でレンダリングする必要があります(MUST)。
__config__、__inputs__、__lists__、シートテンプレート、ディレクティブ、変数をパースする。- ソース行を読む。
- テンプレート式から参照されるソース列を解決する。
output_file_patternからソース行をファイルグループに分割する。- シート名グループキーからファイルグループをシートグループに分割する。
- ディレクティブを現在の行集合に適用する。
- リピートブロックを展開する。
- 静的セルとデータセルを評価する。
- 予約
__<name>__シートとディレクティブ行を出力から除去する。 - 出力ファイルを書き出す。
正確な実装戦略は異なってよいですが、観測可能な出力はこの順序に一致する必要があります(MUST)。
ブロック展開 — 列スコープ splice(ADR-0066)
ステップ 7(「リピートブロックを展開する」)は、splice の列スコープについて規範的です。行範囲 [r_start..r_end] と列範囲 [c_start..c_end] を持つデータブロック(導出方法は language.md の "Data Blocks" を参照)を N レコードへ展開すると、次のようになります。
- Inside cells(列が
[c_start..c_end]内):- 行
[r_start..r_end]: レコードごとにr_start..r_start + N * (r_end - r_start + 1) - 1へクローンします。 - 行
r > r_end:(N - 1) * (r_end - r_start + 1)行だけ下へシフトします。
- 行
- Outside cells(列が
[c_start..c_end]の外):- 展開係数
Nに関係なく、元の(r, c)位置に残ります。 - そのセル値、数式テキスト、スタイルは逐語的に保持される必要があります(MUST)。
- 展開係数
splice の行シフト効果はしたがって列スコープです。同じ OOXML の行挿入は内側列セルだけをシフトし、レンダラは同じレンダーフェーズ内で outside-cell restore pass を行い、外側列セルを元の行位置に戻します。行全体 splice を行う実装は、この契約を満たすために outside-cell restore pass を後続させる必要があります(MUST)。
順序
出力順序は決定論的でソース駆動です。
- ファイルグループは first-seen(最初に出会った順) で現れます。エンジンはソース行をソースの自然な順序で歩き、
output_file_patternがファイル名Xに評価される最初の行が、そのグループを最初にエミットさせます。 - ファイル内のシートグループは、ファイルグループの行リストにわたって first-seen 順 で現れます。最初にマッチした行がシートの位置を決めます。
- 単一ソースの反復順序は、
source_tableを上から下に読む順です。マルチソースデータ(External Data Sources 参照)では、規則はプライマリソースの行に適用されます。名前付きソースは集計と結合に寄与しますが、出力順序には影響しません。
ソートの安定性は @sort で定義されます:等しいソートキーはソース順を保持します。
ディレクティブ
ディレクティブはこの順序で適用されます。
source -> join -> filter -> sort -> group -> top -> repeat
複数のフィルターは論理 AND で結合されます。複数のソートでは、最初の @sort がプライマリキーで、後続のソートがタイブレーカーです。
@group(ADR-0038)は post-filter / post-sort の行集合を N レベルのネストされたグループに分割し、単一のデータブロック内でインターリーブされた @subtotal 行のエミットを駆動します。グループ順は @sort の後の出現順です。@group 自体は並べ替えません。@top はグループ化の後に行レベルで適用されます — 小計行は @top のカットを生き残ったデータ行を持つグループにのみエミットされます。
@repeat right はブ ロックの展開方向を変更するもので、データフィルタリングディレクティブではありません。明示的な @repeat がない場合、データブロックは垂直(下方向)に展開します — ソース行 1 行あたり 1 つのレンダー行。
セルテキスト抽出
テンプレート式のパースとソース行の読み取りは、各セルの有効テキスト/値に対して動作します。
- プレーンな文字列、数値、Boolean、日付セルはそのセル値として読まれます。
- リッチテキストセルは、テキストランを順に連結したものとして読まれます。
- 数式セルは XTL によって再計算されません。ワークブックがキャッシュされた数式結果を含む場合、そのキャッシュ結果が使われます。数式セルがソースデータ値として読まれ、キャッシュ結果が利用できない場合はエラーです。
ソース値モデル
ソース値は以下の種類のいずれかです(ADR-0017 に従う)。
| 種類 | 備考 |
|---|---|
| Missing | ソース列がこの行に存在しない、またはセルが空白。Empty Values に従い空。 |
| String | Unicode テキスト。ADR-0007 に従い、すべて空 白のときのみ空。 |
| Number | IEEE 754 double。NaN と無限大は仕様準拠の演算からは生じない。"" にストリング化され、空として流れる。 |
| Boolean | TRUE / FALSE。 |
| Date | カレンダー上の時点。時刻成分を持つことも持たないこともある。 |
Excel セルの形は種類にマップされます。
| Excel セル | XTL の種類 |
|---|---|
| Blank | Missing |
| String / inline / shared string | String |
| Number(日付形式でないフォーマットでシリアル値として保存された日付を含む) | Number |
| 日付フォーマットのセル | Date |
| Boolean | Boolean |
| キャッシュ結果のある数式 | 結果の種類 |
エラーセル(#N/A、#VALUE!、#DIV/0!、…) | Missing(Empty Values に従う) |
パーセンテージフォーマットの Excel セルは、その基底の Number 値として流れます(50% → 0.5)。フォーマット済み出力が必要なテンプレートは TEXT(value, "0%")(XTL 0.1 コアテーブル外の拡張フォーマット)を使うか、テンプレートセルの数値フォーマットが保持されることを当てにします。
セル評価
単一式セル
セル全体の内容がちょうど 1 つのテンプレート式である場合、そのセルは単一式セルです。
{{ [OrderDate] }}
ADR-0052 に従い、「セル全体の内容」とは、セルテキストから先頭と末尾の Unicode 空白をトリムした後で評価されます。 {{ [OrderDate] }} のような周囲の空白のみのセルは単一式セルです。トリムされた空白はレンダリングされる値の一部ではありません。
セパレータのない隣接テンプレートブロック — {{ [A] }}{{ [B] }} — は単一式セルではありません。これらは下記の規則に従い混在テキストセルであり、結果は正規文字列として結合されます。型を保持する単一式の挙動が欲しい作成者は、明示的な & 形式 {{ [A] & [B] }} を使ってください。
単一式セルは、可能な限り評価値の型を保持します。
テンプレートセルが数値/日付/テキストフォーマットを持つ場合、実装はその形式に合うよう文字列ソース値を強制変換する必要があります(MUST)。
- 日付類似フォーマットは、サポートする日付文字列または Excel シリアル数を日付に強制変換します。