03 · 列的彙總
情境
在資料區塊下方加一個合計列,把上方的資料加總起來。或是把跨來源的彙總值(例如全公司總和)放到表頭儲存格。
純括號彙總 — 作用範圍是資料區塊
{{ SUM([續約金額]) }}
{{ COUNT([續約金額]) }}
{{ AVERAGE([續約金額]) }}
{{ MIN([續約金額]) }}
{{ MAX([續約金額]) }}
在資料區塊內,這些彙總會累加目前迭代的來源列。在頁尾列(位於資料區塊下方、本身不含範本區塊的列)裡,同樣的表達式則參照剛展開完成的整個區塊。
| A1: 客戶 | B1: 續約金額 |
| A2: {{ [客戶] }} | B2: {{ [續約金額] }} | ← 資料區塊
| A3: 合計 | B3: {{ SUM([續約金額]) }} | ← 頁尾
3 筆來源列展開後:第 3 列變成第 5 列,B5 顯示三筆 續約金額 的總和。
指定來源的彙總 — 作用範圍是整個來源
{{ SUM(續約資料[金額]) }} # 整個來源,不是目前的活動區塊
{{ COUNT(客戶資料[客戶]) }}
當你寫 SUM(SourceName[Column]),xl3 會對整個具名來源加總 — 而不是被篩選或被聯結後的區塊。請在頁首裡標示「整體總和」這類不該隨區塊篩選而變動的儲存格時使用。
續約資料 是宣告在 __sources__ 裡的名稱。請參考 食譜 07。
Filter 只改變區塊,不影響來源
{{ @filter [地區] = "台北" }}
{{ [客戶] }} | {{ [續約金額] }}
合計: | {{ SUM([續約金額]) }} # 只算台北列
總計: | {{ SUM(來源[續約金額]) }} # 全部列
SUM([續約金額]) 反映篩選後的區塊。SUM(來源[續約金額]) 則無視篩選。
行不通的寫法 — 彙總內部做算術
SUM、AVERAGE、MIN、MAX、單引數 COUNT 的唯一引數必須是欄位參考([Column] 或 Source[Column])。在彙總內做逐列算術、字面值、函式呼叫,會在 parse 階段以 xl3/eval/bad-aggregate-arg 被拒絕(ADR-0059):
{{ SUM([數量] * [單價]) }} # ✗ 逐列算術 — 拒絕
{{ SUM(1 + 2) }} # ✗ 字面值表達式 — 拒絕
{{ SUM(IF([地區]="台北", [金額], 0)) }} # ✗ 函式呼叫 — 拒絕
{{ AVERAGE([營業額] - [成本]) }} # ✗ 逐列減法 — 拒絕
這是刻意的設計。Excel 的 SUMPRODUCT / 陣列公式語意(先逐列計算再彙總)在 XTL 0.x 不在範圍內 — 請見 ADR-0059 §「Why not allow SUM([a] + [b])」。
解法:在來源端加輔助欄
正規模式(營業額 = Σ 數量 × 單價)是在來源活頁簿裡加一欄逐列乘積,然後把該欄加總:
# 在原始資料中,新增「金額」欄位:
| 數量 | 單價 | 金額 |
| 3 | 100 | =B2*C2 (或先算好的 300) |
| 2 | 150 | =B3*C3 (或 300) |
# 範本:
{{ SUM([金額]) }} # ✓ — 加總預先算好的欄位
如果來源是程式產生的,就直接把乘法結果寫進那一欄。如果是人工維護的活頁簿,就在 金額 欄裡寫一條一般的 Excel 公式。
解法:逐列儲存格 + 頁尾彙總
如果你只是要在展開後的輸出中看到「每列乘積」(不需要加總),就在範本儲存格裡逐列計算:
| {{ [數量] }} | {{ [單價] }} | {{ [數量] * [單價] }} | # ✓ 列層級
之所以可行,是因為 {{ [數量] * [單價] }} 是逐列在迭代時求值,這不同於 SUM([數量] * [單價]) — 若還要把那些乘積加總到頁尾,請改用上面「輔助欄」的方案(或在頁尾儲存格寫一條原生 Excel SUMPRODUCT 公式,xl3 會依 ADR-0046 原樣保留)。
備註
- 彙總會忽略空值(ADR-0007)。
COUNT只算非空值。若要計算所有列(含空值),請對一個永不為空的欄位使用COUNT(Source[必填欄位])。- 對零個非空值做
AVERAGE會回傳空值,不會丟錯。 - 彙總內部的合成表達式(字面值、算術、函式呼叫)會依 ADR-0059 丟出
xl3/eval/bad-aggregate-arg。 - 規格參考:
spec/language.md的「Aggregates」;ADR-0012(來源語意);ADR-0059(引數形態規則)。