跳至主要內容

18 · 群組列與小計輸出

情境

你的發票 / 結算單 / 採購單活頁簿,把明細列依客戶或月份分區段,每個區段後面接小計列、(選擇性地)最底下放一條總計列:

台灣物流 產品 A 10,000
台灣物流 產品 B 5,000
小計 15,000
高雄貝塔 產品 A 20,000
小計 20,000
總計 35,000

XTL 0.6 提供兩個指示子,可以在單一資料區塊裡完成這件事,不必在來源端預先彙總、也不必對輸出做後處理(ADR-0038)。

兩個元件

@group [Key1], [Key2], …

@group 把活動列集合切成 N 層巢狀群組,以便交錯輸出小計。它不會重新排序 — 群組順序是 @filter / @sort 套用之後的出現順序。想要穩定的群組順序,請對相同鍵搭配 @sort

{{ @sort [客戶] }}
{{ @group [客戶] }}

@subtotal <aggregate>

含有 {{ @subtotal SUM([金額]) }} 表達式的儲存格所在的列是小計列。它不會逐來源列迭代;取而代之,渲染器會在每個群組邊界、依該列綁定的層級輸出一次。支援的彙總:SUMCOUNTAVERAGEMINMAX

來源順序中第一個 @subtotal 列綁定到最內層的群組鍵。下方再放更多 @subtotal 列,每多一列就綁定到更外層 — 最底下的列綁定到最外層的鍵。

單層分組

{{ @sort [客戶] }}
{{ @group [客戶] }}
{{ [客戶] }} | {{ [品項] }} | {{ [金額] }}
"小計" | | {{ @subtotal SUM([金額]) }}

對於 3 筆來源列(台灣物流/產品 A/100、高雄貝塔/螺絲/50、台灣物流/齒輪/200)渲染出:

台灣物流 產品 A 100
台灣物流 齒輪 200
小計 300
高雄貝塔 螺絲 50
小計 50

兩層巢狀 + 總計

{{ @sort [地區] }}
{{ @sort [客戶] }}
{{ @group [地區], [客戶] }}
{{ [地區] }} | {{ [客戶] }} | {{ [金額] }}
"客戶小計" | | {{ @subtotal SUM([金額]) }}
"地區小計" | | {{ @subtotal SUM([金額]) }}

最上面的 @subtotal 列(客戶小計)綁到最內層鍵([客戶]);下一列(地區小計)綁到 [地區]。兩者都在邊界輸出;當兩個邊界同時結束時,內層先 fire。

「用最外層 @subtotal 做總計」模式:用一條 @group [客戶] 加兩條 @subtotal 列,外層那條會在資料區塊結尾剛好 fire 一次 — 因為最外層群組的邊界就是資料的結尾。

與其他指示子的組合

指示子互動
@filter篩選分組之前套用。被篩掉的列不屬於任何群組。所有列都被篩掉的群組就不會出現。
@sort排序在分組之前套用。要固定群組順序,請以與 @group 相同的鍵與順序 @sort
@source每個 @source 區塊都有自己獨立的分組 scope。
@join聯結列的欄位可以像主列欄位一樣參與分組。群組鍵可以參照聯結欄位。
@top在分組之後對列層級套用。@top cut 後仍有資料列的群組才會輸出小計。
@repeat right不相容於 @groupxl3/directive/invalid-syntax)。

邊界案例

  • 單一群組退化 — 若 @group [Key] 且所有列共用同一個 [Key] 值,小計仍會在該群組邊界輸出一次。當資料集恰好只有一個外層群組值時,正好對應到總計模式。
  • 空群組 — 所有資料列依 ADR-0007 都為空的群組會被跳過:資料列與 @subtotal 都不輸出。
  • 彙總引數@subtotal 內只接受欄位參考。合成表達式(SUM([A]) - SUM([B])IF(...))會丟 xl3/subtotal/bad-aggregate,延後處理。
  • @subtotal 列的字面文字儲存格 — 可以;「小計:」標籤可放在彙總儲存格旁邊,每次輸出時一起渲染。但字面儲存格不可參照當前列欄位 — 群組邊界沒有「當前列」。

錯誤碼

  • xl3/group/missing-key@group 沒有鍵清單。
  • xl3/subtotal/outside-group@subtotal 出現在沒有 @group 的區塊,或 @subtotal 列數多於 @group 鍵數。
  • xl3/subtotal/bad-aggregate — 內容不是 SUMCOUNTAVERAGEMINMAX 之一,或引數不是欄位參考。

延伸閱讀