跳至主要內容

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(來源[續約金額]) 則無視篩選。

行不通的寫法 — 彙總內部做算術

SUMAVERAGEMINMAX、單引數 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(引數形態規則)。