跳至主要內容

XTL 評估模型

備註

本繁體中文版本僅供閱讀輔助。規格的正典為英文原版,若規範性解讀有差異,以英文為準。

本文件定義 XTL 實作如何讀取輸入並產生輸出。

輸入與輸出

一次 XTL 轉換接受:

template.xlsx
data.xlsx

並產生一個或多個 .xlsx 輸出檔案。

範本活頁簿定義輸出活頁簿的形狀、範本運算式、群組規則、指令以及組態。來源活頁簿則提供表格化資料。

保留工作表

xl3 定義了四個保留的工作表名稱。任何名稱符合 以 dunder 包覆樣式 __<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來源工作表名稱,或以 * 結尾的前綴樣式OrdersData_*
source_table來源資料表選擇器。第一個被選到的列包含欄名稱;下方各列為資料。1A1:DB5: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)。

外部資料來源

範本可以MAY)透過提供保留工作表 __sources__ 來宣告 預設來源以外的命名資料來源。第 1 列為標題;之後每一列 宣告一個來源。

必填意義
name來源名稱。僅可使用字母、數字與底線。不得__ 開頭,不得default(保留給隱含來源)。
sheet資料活頁簿中的來源工作表名稱,或以 * 結尾的前綴樣式。
table該工作表的來源資料表選擇器,預設為 1。語法同 __config__source_table
description自由格式註記。

實作必須MUST)依標題文字識別欄位,不分大小寫。

隱含的 default 來源——透過 __config__ 中的 source_sheetsource_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 指令(見 Directives)。

未指定 @source 時,作用中來源為 default@source 必須MUST)出現在同一區塊的 @filter@sort@top 指令之前(因為它決定這些指令要對哪個列集合運算)。

參考未宣告的來源——不論是透過 @source <Unknown> 還是 透過 Unknown[Column]——皆為錯誤。

@join 指令

資料區塊可以MAY)在 @source 之後緊接著加上 一個 @join 指令,將主來源的每一列與第二個來源的某一列配對:

{{ @source Renewals }}
{{ @join Customers on Customers[Account] = Renewals[Account] }}
{{ [Account] }} | {{ Customers[Name] }} | {{ [Amount] }}

對每一主來源列,引擎會找出 第一個 比對成功的被連接列 (依 Comparison Algorithm) 並渲染這對列。「第一個」由被連接來源的自然列順序決定—— 即在其 source_table 範圍內由上到下。這是規範性的:當多個 被連接列具有相同的連接鍵時,兩個實作必須MUST)挑出 相同的配對列。

如果找不到比對,主來源列會被 丟棄(內連接語意)。

在區塊內,[Column]<PrimarySource>[Column] 解析到 主來源列;<JoinedSource>[Column] 解析到配對的被連接列。 列層級對其他來源的參考仍為錯誤。

多個 @join 指令、左連接語意、多列比對皆不在 XTL 0.1 範圍內。

輸入

範本可以MAY)透過提供保留工作表 __inputs__ 來宣告 執行階段輸入。第 1 列為標題;之後每一列宣告一個輸入。

必填意義
name輸入名稱。僅可使用字母、數字與底線。
typetextnumberdateselect 其中之一。
default若非空,當宿主未提供該輸入時使用。預設值會依該輸入的 type 解析。
label給人看的提示文字。宿主應該SHOULD)將其作為表單標籤。
description選填的較長說明。
optionstype = select 時為必填。以管線符號分隔的允許值,例如 Seoul|Busan|Daegu

實作必須MUST)依標題文字識別欄位,不分大小寫。 未列於上方的欄位為保留欄,必須MUST)忽略。

當某輸入的列沒有 default 時,該輸入即為 必填。宿主 必須MUST)提供每個必填輸入;遺漏任一個即為錯誤。

解析後的輸入值從儲存格透過 {{ __inputs__[name] }} 參考。 例如,宣告為 name = month 的輸入可用 {{ __inputs__[month] }} 參考。__inputs__[name] 解析到「解析後且強制轉型後」的值; 規格中沒有從範本內部讀取輸入的 labeldefaulttype 的形式(宿主請使用 readTemplateInputs() API)。

輸入名稱不得MUST NOT)與 __config__ 中宣告為非系統 列的作者自訂值名稱衝突;這在解析階段就是錯誤。

依 ADR-0062,當 default 儲存格於 經過 ADR-0050 評估後 產生的值依 ADR-0007 為空時,該輸入為 必填。包含 「空白儲存格」、default = ""default = " "default = {{ "" }} 等形式,皆會塌縮為「必填」。

依 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——以「修剪後再以 Number() 解析,且不得產生 NaN」 解析。失敗為錯誤。
  • date——以與日期格式單一運算式儲存格相同的規則強制轉型。 失敗為錯誤。
  • select——宿主值經正規字串形式正規化後必須MUST) 等同於某個已宣告的 options。失敗為錯誤。

強制轉型後的輸入值可如同其他值一樣參與 IF()@filter&、比較以及 TEXT()

default / label / description / options 中的範本評估

依 ADR-0050,defaultlabeldescriptionoptions 四欄中的儲存格本身就是 XTL 範本:連續文字加上零或多個 {{ ... }} 區塊,在讀取輸入時(任何來源列載入之前)評估。 此時的評估上下文被刻意限制。

可用繫結:

  • __config__[key]——來自 __config__ 工作表的作者自訂值 (__config____inputs__ 之前先解析)。
  • 純量函式:TODAYDATEIFIFEMPTYIFSIFERRORUPPERLOWERTRIMTEXTYEARMONTHDAYEOMONTHEDATEDATEDIFROUNDABS

禁止的繫結(引發穩定錯誤碼):

  • [Column]Source[Column] 參考——在讀取輸入時尚無 來源列上下文。錯誤:xl3/inputs/forward-reference
  • __sources__[…]__inputs__[name]——來源尚未載入; 輸入列為各自獨立的宣告。錯誤: xl3/inputs/forward-reference
  • ROW()SUMCOUNTAVERAGEMINMAXXLOOKUP ——屬於渲染階段或依賴來源資料。錯誤: xl3/inputs/runtime-only-fn

評估後的正規字串形式(見 ADR-0009)即是透過宿主 UI 回傳的 InputSpec.default / InputSpec.label / InputSpec.description。對於 options,評估後的字串 會再以 | 分割產生陣列。

對於 default,評估後的字串會再依該輸入宣告的 type 依上述規則強制轉型。因此 default = {{ TODAY() }} 加上 type = date,會在轉型後的預設值中產出渲染階段的 ISO 日期。

來源資料模型

來源資料模型是一個有序的列清單。每一列是來源欄名稱到 儲存格值的映射。

source_sheet 選擇工作表。若省略,使用第一個工作表。 若 source_sheet* 結尾,視為前綴樣式。實作 必須MUST)依活頁簿順序選擇第一個名稱以 * 之前 前綴開頭的工作表。若無工作表符合,為錯誤。完全相符 的工作表名稱優先於前綴比對。

source_table 在選定的工作表內解讀:

形式意義
NN 列包含來源欄名稱。來源欄是從第一個非空儲存格到最後一個非空儲存格之間的非空儲存格。N 以下各列為資料列,直到工作表已使用列的尾端。
A1:DA1:D1 儲存格包含來源欄名稱。下方各列為資料列,直到工作表已使用列的尾端。
A1:D200A1:D1 儲存格包含來源欄名稱。A:D 欄的第 2:200 列為資料列。

若省略 source_table,預設為 1

N 必須MUST)為 1 起始的正整數。範圍形式 必須MUST)使用絕對 Excel A1 座標,包含左欄、起始列、 右欄與選填的結束列。左欄不得位於右欄之右側。選填的結束 列不得位於起始列之上。

當範圍形式的結束列等於起始列時,例如 A1:D1,該來源資料表 僅包含欄名稱且資料列為零。此情形有效。

來源資料表的欄名稱儲存格使用與來源資料儲存格相同的有效文字/ 值擷取規則,且在修剪之前進行。

欄名稱規則:

  1. 來源欄名稱儲存格的值會轉成字串並修剪。
  2. 來源欄名稱區分大小寫。
  3. 富文字的來源欄名稱儲存格以串接其文字段落讀取。
  4. 公式儲存格的來源欄名稱使用其快取的公式結果。若無快取結果, 為錯誤。
  5. 在選定的來源資料表內,空欄名稱為錯誤。
  6. 重複的來源欄名稱為錯誤。
  7. 空資料列會被略過。
  8. 水平合併的標題儲存格在合併主儲存格的欄索引位置形成一個欄 (依 ADR-0033)。同一列、與主儲存格不同欄的從屬儲存格屬於 透明:它們既不貢獻欄,也不會造成重複名稱錯誤。標題列中的 垂直合併在從屬儲存格的欄位置原樣讀取主儲存格的文字。若 選定範圍只包含合併的從屬儲存格(視窗內沒有主儲存格), 為錯誤(xl3/source/missing-header);請擴大範圍以納入 合併主儲存格。
  9. 標題儲存格文字中的換行符(CRLF、CR 或 LF——包含透過 Alt+Enter 產生的)會在讀取時依 ADR-0041 修訂正規化為單一空白 (U+0020)。連續多個換行會合併為一個空白。空白合併後的形式 就是欄名稱;範本以同樣的空白形式參考({{ [單位: 元] }})。 修剪以及修剪後為空的偵測(規則 5)會在換行正規化之後 套用。標題的正規化與資料列不對稱,依 ADR-0041 原始範圍, 資料列中的 LF 會原樣保留。

資料列(標題列以下的列)的合併儲存格依 ADR-0035 適用 另一條規則:合併從屬儲存格的值等於合併主儲存格的值。橫跨 N 個資料列的垂直合併會產生 N 個資料列,每列在該欄共享 主儲存格的值。資料列中的水平合併會讓每個從屬欄都在該列 拿到主儲存格的值。空資料列略過會在合併廣播 之後 評估。 作者若希望讓垂直合併算作單一邏輯紀錄,應該SHOULD) 取消來源資料區的合併。

對於列號簡寫(source_table = N),在推斷出來源欄跨度之後, 第一個與最後一個非空欄名稱儲存格之間的空缺即為錯誤。

空值

當某值為缺值時即為——該來源欄在這一列不存在,或儲存格為 空白——或者它是一個內容全是 Unicode 空白的字串。

數字(包括 0)永遠不是空。布林(包括 false)永遠不是空。 日期永遠不是空。非空字串永遠不是空。快取結果為空字串的公式 依本規則為空。

Excel 錯誤儲存格(#N/A#VALUE!#DIV/0!#REF!#NAME?#NUM!#NULL!)——無論是靜態值或是作為公式 的快取結果——依此規則也為空(ADR-0017)。實作可以MAY)在遇到時送出警告;警告不得MUST NOT)改變 輸出語意。

空值述詞掌管規格中所有提到空值的地方:

  • value 為空時,IFEMPTY(value, fallback) 回傳 fallback
  • COUNT([field]) 僅在某列的 [field] 值非空時才計入該列。
  • 當來源資料表欄跨度的每個儲存格皆為空時,該來源列為空。 空資料列會在分群與渲染之前略過。
  • 清單工作表的條目以丟棄該工作表第一欄中的空儲存格的方式讀取。
  • 空的來源列值永遠不會比對到 @filter [field] in __lists__[name]。相同的值永遠會比對到 @filter [field] !in __lists__[name]

清單工作表

範本可以MAY)透過提供保留工作表 __lists__ 來宣告 命名的成員資格清單。第 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)依此概念順序渲染:

  1. 解析 __config____inputs____lists__、工作表範本、指令與變數。
  2. 讀取來源列。
  3. 解析範本運算式所參考的來源欄。
  4. output_file_pattern 將來源列切分為檔案群組。
  5. 依工作表名稱群組鍵將檔案群組切分為工作表群組。
  6. 對目前列集合套用指令。
  7. 展開 repeat 區塊。
  8. 評估靜態儲存格與資料儲存格。
  9. 從輸出中移除保留的 __<name>__ 工作表與指令列。
  10. 寫出輸出檔案。

實際實作策略可能不同,但可觀察到的輸出必須MUST) 與此順序一致。

區塊展開——欄範圍 splice(ADR-0066)

步驟 7(「展開 repeat 區塊」)對 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 列插入只會位移內部欄儲存格,渲染器會在同一渲染階段將外部欄儲存格恢復到其原始列位置。執行整列 splice 的實作必須MUST)接著執行 outside-cell restore pass,才能滿足此契約。

排序

輸出排序具有決定性,由來源驅動:

  • 檔案群組首見 順序出現。引擎以來源自然順序走訪 來源列;第一個 output_file_pattern 評估出檔名 X 的列 會讓該群組第一個發出。
  • 同一檔案內的工作表群組首見 順序出現,於該檔案 群組的列清單之上。第一個比對到的列決定該工作表的位置。
  • 單一來源的迭代順序就是 source_table 由上到下的讀取順序。 在多來源資料情境下(見 External Data Sources),此規則適用於 主要 來源的列;命名來源會貢獻彙總與連接,但不影響輸出排序。

排序穩定性定義於 @sort:相等的排序鍵會保留來源順序。

指令

指令依此順序套用:

source -> join -> filter -> sort -> group -> top -> repeat

多個篩選以邏輯 AND 結合。若有多個排序,第一個 @sort 是 主鍵,後續的排序為次鍵。

@group(ADR-0038)會將篩選後/排序後的列集合分割成 N 層 巢狀群組,並在單一資料區塊內驅動穿插的 @subtotal 列輸出。 群組順序是 排序後 的遇見順序;@group 本身不會重新排序。 @top 在群組之後於列層級套用——只有資料列在 @top 切分 後仍存活的群組才會發出小計列。

@repeat right 改變區塊展開方向,並非資料篩選指令。沒有 顯式 @repeat 時,資料區塊預設垂直展開(向下)——每個來源 列產生一個渲染列。

儲存格文字擷取

範本運算式解析與來源列讀取會作用於每個儲存格的有效文字/值:

  • 純字串、數字、布林、日期儲存格依其儲存格值讀取。
  • 富文字儲存格以其文字段落串接讀取,依序串接。
  • 公式儲存格不會被 XTL 重新計算。若活頁簿包含快取的公式結果, 使用該快取結果。若公式儲存格被當作來源資料值讀取且無快取 結果,為錯誤。

來源值模型

來源值為下列其中一種類型(依 ADR-0017):

類型備註
Missing該來源欄在這一列不存在,或儲存格為空白。依 Empty Values 為空。
StringUnicode 文字。僅在全為空白時依 ADR-0007 為空。
NumberIEEE 754 雙精度。NaN 與無限值不會由符合規範的運算產生;它們會字串化為 "" 並以空值流動。
BooleanTRUE / FALSE
Date一個行事曆瞬間;可以MAY)攜帶或不攜帶時間元件。

Excel 儲存格形狀對應至各類型:

Excel 儲存格XTL 類型
空白Missing
字串/內聯/共享字串String
數字(包含以序號儲存且套用非日期格式的日期)Number
採用日期格式的儲存格Date
布林Boolean
含快取結果的公式該結果的類型
錯誤儲存格(#N/A#VALUE!#DIV/0!、…)Missing(依 Empty Values

採用百分比格式的 Excel 儲存格會以底層的 Number 值流動 (50% → 0.5)。需要格式化輸出的範本可使用 TEXT(value, "0%") (屬於 XTL 0.1 核心表以外的擴充格式),或依賴範本儲存格的數字 格式被保留。

儲存格評估

單一運算式儲存格

當儲存格的完整內容就是一個範本運算式時,即為單一運算式儲存格:

{{ [OrderDate] }}

依 ADR-0052,所謂「完整內容」是針對儲存格文字在 修剪前後 Unicode 空白後進行判斷。內容為 {{ [OrderDate] }} (僅前後空白)的儲存格也是單一運算式 儲存格。被修剪掉的空白不算在渲染後的值內。

相鄰、之間無分隔字元的範本區塊——{{ [A] }}{{ [B] }}—— 不是 單一運算式儲存格。依下方規則它們屬於混合文字儲存格; 其結果會以正規字串串接。作者若想保留型別的單一運算式行為, 請使用明確的 & 形式:{{ [A] & [B] }}

單一運算式儲存格盡可能保留評估後的值類型。

若範本儲存格設定了數字/日期/文字格式,實作必須MUST) 將字串型的來源值強制轉型以符合該格式:

  • 類日期格式會將支援的日期字串或 Excel 序號強制轉型為日期。
  • 類數字格式會將數值字串強制轉型為數字。
  • 文字格式 @ 會強制轉型為字串。

若強制轉型失敗,實作必須MUST)回報錯誤。

XTL 0.1 並未規範性地定義最少需支援的日期格式集合與數字格式 標記,留給各實作決定。支援的格式數量少於另一實作者,可宣告 部分符合性。

混合文字儲存格

當儲存格在一個或多個運算式周圍含有字面文字時,即為混合文字 儲存格:

Order date: {{ [OrderDate] }}

依 ADR-0052,包含相鄰且無分隔字元的範本區塊 ({{ [A] }}{{ [B] }})的儲存格同樣是混合文字儲存格。

混合文字儲存格以字串渲染。範本的數字/日期格式不會對混合 文字儲存格強制轉型。依 Empty Values 為空 的值(包括依 ADR-0053 的六種來源端 Excel 錯誤標記)在其 位置貢獻 "";引擎產生的 #DIV/0! 則在其位置代入字面字串 "#DIV/0!"(ADR-0025)。

TEXT 函式

對於 XTL 0.1 核心格式,TEXT(value, format) 回傳字串。它的 用途是檔名與明確的顯示字串,並非用於應保持為數字/日期值的 儲存格。

XTL 0.1 核心 TEXT() 表以外的格式屬於實作定義擴充。符合性 語料庫不會對這些格式宣告特定結果。

輸出檔名

output_file_pattern 評估產生的每個輸出檔名必須MUST) 依此順序消毒:

  1. 替換禁用字元_
    • 集合 < > : " / \ | ? *
    • ASCII 控制字元,範圍 0x00-0x1F
  2. 修剪 前後空白以及尾端的 . 字元。
  3. 保留名稱保護: 若結果的主檔名(在 .xlsx 副檔名之前), 不分大小寫等同於 CONPRNAUXNULCOM1-COM9LPT1-LPT9 之一,則在主檔名後加上一個 _
  4. 若步驟 1-3 後產生空檔名或空主檔名,為錯誤。
  5. 若結果檔名的 UTF-8 位元組長度超過 255,為錯誤。實作 不得MUST NOT)默默截斷。
  6. 當步驟 1-3 改動了渲染後字串時,實作應該SHOULD) 送出警告,內容包含原檔名與消毒後檔名。警告 不得MUST NOT)改變輸出語意。

這些規則僅適用於檔名。工作表名稱遵循 Excel 自家的禁用集合 與 31 字元長度上限,由實作另行定義。

Unicode 字元(例如 CJK、附加重音的字母、表情符號)不受限制: 任何不在明確禁用集合中的碼點皆會保留。

樣式與活頁簿結構

實作必須MUST)在渲染輸出中原樣保留以下範本特性 (依 ADR-0036):

  • 儲存格樣式(字型、填滿、框線、對齊)
  • 數字/日期格式
  • 列高與欄寬
  • 範本與來源資料列中的合併儲存格(來源標題依 ADR-0033、 來源資料列依 ADR-0035)
  • 圖片以及其錨點範圍
  • 條件式格式規則以及其 sqref 範圍
  • 命名範圍/已定義名稱(活頁簿層級與工作表層級)
  • 列印範圍與列印標題(重複列/欄)
  • 凍結窗格/分割(工作表的 views
  • 工作表保護狀態,以及每個儲存格的鎖定/隱藏旗標
  • 資料驗證規則(下拉清單、範圍限制)以及其範圍
  • 儲存格註解(備註)

這些內容會 原樣 保留。範圍、錨點與參考在 @repeat 展開 列時 不會 自動延伸:引擎會原封不動地把範本的編碼帶到 輸出。若作者需要某條規則(例如條件式格式)涵蓋 repeat 展開的列,應該SHOULD)在範本中以整欄參考錨定 (例如 $A:$A),而非倚賴引擎端的延伸。

圖表在 XTL 0.1 中為 實作定義(依 ADR-0036 第 3 項 與 ADR-0006);移植版可以保留、遺失或部分保留圖表物件。 未來 ADR 會在 Stage 2 符合性涵蓋圖表時,規範性地釘住 圖表行為。

樣式保留不會凌駕值語意。例如,TEXT() 回傳的字串即便所在 範本儲存格設了日期格式,也仍是字串。

錯誤

以下情境為錯誤:

  • 參考不存在的來源欄(xl3/source/unknown-column)。
  • 參考未在 __sources__ 中宣告的來源(xl3/source/undeclared)。
  • 參考 __lists__ 內不存在的清單 (xl3/lists/missing-reference)。
  • 使用無效的指令。
  • 使用無效的 source_table
  • 使用空白或重複的來源欄名稱。
  • 作者建立的工作表名稱符合保留 dunder 樣式 ^__[a-z]+__$(依 ADR-0011,xl3/sheet/reserved-name)。
  • __sources__ 宣告工作表當作值字典參考 (例如 __sources__[Customers]xl3/sources/not-a-dictionary);應直接使用來源名稱。
  • 將單一運算式儲存格的值強制轉型為其範本儲存格格式失敗 (xl3/cell/numfmt-coercion)。
  • 套用消毒規則後產生無效輸出檔名 (xl3/filename/emptyxl3/filename/too-long)。
  • 在 repeat 區塊外呼叫 ROW()xl3/cell/row-outside-repeat)。
  • 來源公式儲存格沒有快取結果 (xl3/cell/formula-no-cache)。
  • 遺漏必填的 __inputs__xl3/inputs/missing-required)、 無效輸入值,或 select 值不在 options 內 (完整輸入錯誤目錄見 ADR-0010)。
  • XLOOKUP 無比對且無 fallback(xl3/xlookup/no-match)、 裸方括號引數(xl3/xlookup/bare-bracket),或來源不匹配 的陣列(xl3/xlookup/source-mismatch)。
  • @join 參考未宣告的來源 (xl3/join/undeclared-source),或格式錯誤的 on 子句 (xl3/join/bad-on-clause)。
  • 列層級參考非作用中來源的欄 (xl3/source/row-cross-block)。
  • 不支援的運算式語法——一元 +--,或對非字面值 (欄參考、保留工作表參考或子運算式)的一元 -xl3/eval/unsupported-syntax,依 ADR-0028)。
  • 無效的指令語法——同一資料區塊內重複的 @source@join,或空的指令本體 (xl3/directive/invalid-syntax,依 ADR-0029); @top@repeat right 的整數不大於等於 1 (依 ADR-0055)。
  • 範本區塊含有不平衡的字串字面值——通常是 "..." 內嵌了 }}xl3/parser/unbalanced-literal,依 ADR-0051)。
  • 資料儲存格中的裸識別字無法解析為布林字面值 (xl3/expression/unknown-name,依 ADR-0054)。
  • @filter ... in / @filter ... !in 位置以外使用 __lists__[name] 參考(xl3/lists/invalid-use, 依 ADR-0057)。
  • 彙總函式(SUMAVERAGEMINMAX、單引數 COUNT)的引數不是 [Column]Source[Column] 參考 (xl3/eval/bad-aggregate-arg,依 ADR-0059)。

依 ADR-0015,每個規格定義的錯誤都附帶形如 xl3/<category>/<id> 的穩定 error.code。宿主以此碼進行 在地化與程式化分派;英文版的 Error.message 仍是符合性 契約。

實作可以MAY)為非致命的可攜性議題提供警告,但警告 不得MUST NOT)改變輸出語意。

資源限制

規格層級的立場

資源限制——最大輸入範本大小、最大來源列數量、最大輸出活頁簿 大小、@repeat 的最大迭代次數、最大遞迴深度——皆為 實作定義。XTL 0.1 規格並未強制特定上限。實作應該SHOULD)記錄自身限制,並應該SHOULD)在達到限制 時引發穩定的 xl3/limits/... 錯誤碼,但這些代碼本身並非 規格契約的一部分,因為宿主在部署形態(瀏覽器、CLI、伺服器) 與威脅模型上差異甚大。

接受不受信任範本的宿主(例如接受使用者上傳 .xlsx 的 SaaS) 必須MUST)在引擎之上的層級執行自己的限制—— 沙箱化、請求大小上限、逾時——並不應SHOULD NOT) 依賴引擎偵測惡意輸入。

實作限制——參考實作(xl3-js)

參考實作公布以下軟性上限(ROADMAP gate G21)。這些是 正確性界限,而不是安全界限——接受不受信任輸入的宿主 必須MUST)依 SECURITY.md 加入 自己的執行層。下列數值為 0.6.0 的草案,隨著 bench 語料庫 (G8)落地會收緊。

維度軟性上限(草案)達到上限時的行為
每個區塊的來源列數1,000,000實作定義;ExcelJS 的記憶體模型是瓶頸
每個輸出工作表的總儲存格數Excel 的 17,179,869,184(1,048,576 × 16,384 硬上限)xl3 不會合成超過 Excel 工作表上限的儲存格;若輸出會超過上限則引發錯誤
@repeat 迭代次數受來源列數限制沒有獨立的迭代上限;來源本身就是節流器
__sources__ 數量實作定義;規格無限制宣告的上限僅以警告呈現
檔案群組輸出數實作定義參考實作每群組發出一個檔案;宿主應該SHOULD)在外部設定上限

串流政策

參考實作在 1.x 中會將範本與資料完整載入記憶體。串流 I/O 明確延後到 1.1+:它需要正規化、浮水印與背壓 API,而這些 都會改變公開介面。需要大規模轉換的宿主應該SHOULD) 在 來源 邊界分片(把一個 10M 列的資料表分成 10 個 1M 列的 轉換),而不是等待串流。

AbortSignal

convert()preview() 在其 options 引數上接受選填的 AbortSignal(依 gate G21 規劃於 0.7-0.8)。當訊號中止時, 進行中的轉換會引發穩定錯誤碼(xl3/abort/cancelled); 不會輸出任何部分結果。需要將轉換與牆鐘預算競賽的宿主, 可用此鉤點以決定論方式執行逾時。

此 API 為向前相容——將該選填引數加入 ConvertOptions 不影響既有呼叫端;該錯誤碼依 ADR-0015 為附加式(append-only)。