公式型別:formula
用途
formula 用現有欄位推導數字、精確小數、布林或字串,例如訂單明細的「小計 = 單價 × 數量」、庫存表的「需要補貨 = 庫存 < 安全水位」,或把姓氏與名字串成顯示名稱。預設為 live 公式,每次讀取紀錄時由伺服器求值。
本頁說明 legacy 版本 1(省略 formula_version 時的預設)。明確選用公式 v2可使用型別化擴充函式、版本化工作日及選用 stored 結果;同列相依規則與本頁 v1 跨表範例不同。Commands 尊重選定公式版本。
建立 schema
以下是 columns.create body。被引用欄位必須先存在:
{
"name": "小計",
"type": "formula",
"expression": "[單價] * [數量]",
"description": "未稅小計"
}顯示名稱與 col_<hex> 都可放在方括號中。伺服器會把引用改寫成內部鍵保存,再於回應中盡可能轉回顯示名稱;名稱含 [、] 或 -> 時,必須直接使用內部鍵。
運算子與函式
| 類別 | 語法 | 行為 |
|---|---|---|
| 算術 | +、-、*、/、一元 - | 只接受數值;除以 0 回 null。運算元含 decimal 時 / 會被拒絕,請改用 DIVIDE |
| 比較 | <、<=、>、>=、==、!= | 回布林值;不支援鏈式比較 |
| 分組 | ( ) | 調整算術優先序;比較不可藏在一般括號內 |
| 條件 | IF(condition, then, else) | 依條件選一個分支;兩分支型別必須相容 |
| 邏輯 | AND(a, b)、OR(a, b) | 至少兩個參數,回布林值 |
| 字串 | CONCAT(a, b)、UPPER(x)、LOWER(x)、LEN(x) | 字串組合、大小寫與長度 |
| 日期 | TODAY()、YEAR(x)、MONTH(x)、DATEDIFF(a, b) | 回日期字串、年月數字或相差天數 |
| 小數 | DECIMAL(x)、QUANTIZE(x, scale, MODE)、DIVIDE(a, b, scale, MODE) | 精確轉換、捨入到 scale 位,以及捨入到 scale 位的除法;見精確小數公式 |
設有公司業務時區時,TODAY() 使用該時區,每個 evaluation unit 固定使用一個時間點與日曆版本。業務時區為 null 時沿用伺服器當地日期,不會重寫既有值。
例如把數值比較與條件組合:
{
"name": "覆核等級",
"type": "formula",
"expression": "IF(AND([金額] > 10000, [折扣率] > 0.2), 2, 1)"
}跨表引用
語法 [LinkCol -> TargetNumericCol] 可沿本表的 cardinality-one link 讀取目標表的 integer 或 float:
{
"name": "可用額度",
"type": "formula",
"expression": "[客戶 -> 信用額度] - [本次金額]"
}跨表引用與 lookup 使用同一套權限遮蔽,但它只是 formula 的求值輸入,不會額外建立可獨立顯示的 lookup 欄。many link 會產生清單,因此不允許直接跨表引用;請先建立 rollup,或改用 one link。每個公式最多 5 組不同跨表 hop,整張表最多 30 組。
精確小數公式
公式只要讀取 decimal 欄位——不論是直接讀取,或透過 decimal 的 lookup、rollup 或 formula——或呼叫 decimal 函式,就會改用精確小數運算求值,而不是二進位浮點數:
+、-、*、一元-與比較運算都是精確的。可以混用integer欄位與數字字面值,但結果為 decimal 的公式不能引用float欄位(decimal formulas cannot mix float columns)。/會被拒絕:decimal division requires DIVIDE(value, value, result_scale, mode)。DECIMAL(x)把數字轉成 decimal。QUANTIZE(x, scale, MODE)把 decimal 捨入到scale位,DIVIDE(a, b, scale, MODE)把兩個 decimal 相除並捨入到scale位。它們的值運算元必須已經是 decimal,因此請用DECIMAL(...)包住integer欄位或字面值。scale是 0 到 18 的字面整數,MODE是HALF_EVEN、HALF_UP、DOWN、FLOOR或CEILING。- decimal 結果是沒有指數、沒有尾端零的純小數字串,例如
"1354.5",即使經過QUANTIZE也一樣。運算元為 null 或float、DIVIDE除以 0,或中間值超過 128 位時,cell 會顯示null。
{
"name": "含稅價",
"type": "formula",
"expression": "QUANTIZE([定價] * 1.05, 2, HALF_UP)"
}這裡的 定價 是 decimal 欄位。對 decimal 公式做計算欄篩選與排序仍然是精確的:當查詢範圍內有列無法精確求值時,請求可能以 ct.numeric_overflow 或 ct.numeric_invalid 失敗,而不是默默略過該列。
合法與不合法的值
formula 是唯讀欄;寫紀錄時必須省略公式值:
{
"data": {
"數量": 2,
"單價": 1290.5
}
}自行送出「小計」會被拒,即使值剛好等於伺服器計算結果:
{
"data": {
"數量": 2,
"單價": 1290.5,
"小計": 2581.0
}
}以下 expression 也不合法:單一 = 不是相等運算子,鏈式比較不支援。
{
"name": "錯誤公式",
"type": "formula",
"expression": "[數量] = 2 < 3"
}顯示與回傳
公式值在讀取時計算並併入 data。算術回數字(運算元含 decimal 時是小數字串)、比較與 AND/OR 回布林、字串函式回字串:
{
"data": {
"數量": 2,
"單價": 1290.5,
"小計": 2581.0
}
}任一必要運算元為 null、除以 0、非有限結果、依賴失效、循環或超深時,cell 會降級為 null,不會讓整頁讀取失敗。公式鏈最多 5 層;expression 最長 1000 字、括號最深 20 層、欄位引用最多 20 個,而且 AND、OR 與 CONCAT 各最多接受 20 個引數。
用 columns.preview 在伺服器試算
在真正建立前,把完全相同的 body 送到 columns.preview。成功時回正規化設定與前 5 筆 sample:
{
"valid": true,
"normalized": {
"name": "小計",
"type": "formula",
"required": false,
"default_value": null,
"max_length": null,
"description": "未稅小計",
"precision": null,
"scale": null,
"allow_negative": null,
"result_scale": null,
"rounding_mode": null,
"target_table_id": null,
"cardinality": null,
"link_field": null,
"aggregation": null,
"target_column": null,
"direction": null,
"source_table_id": null,
"match": null,
"filter": null,
"expression": "[單價] * [數量]",
"options": null,
"restricted": null
},
"sample": [
{
"record_id": "33333333-3333-4333-8333-333333333333",
"value": 2581.0
}
],
"errors": [],
"hint": null
}引用型別、循環或跨表設定錯誤會以 valid: false 與 errors[].field/message/hint 回傳。純語法錯誤更早就會被伺服器的 ColumnCreate 驗證器拒絕:columns.create 與 columns.preview 都回 422(preview 不會把它報成 valid: false),錯誤訊息包含 invalid formula expression:,例如上面的無效範例會得到 invalid formula expression: use '==' for equality (position 11)。語法錯誤包括不支援的字元(如 %)、單一 =、連鎖比較、括號內的比較、未知的函式或捨入模式名稱、引數個數不對的函式呼叫,以及超過 20 層括號、20 個欄位引用或單一呼叫 20 個引數;expression 超過 1000 字同樣是 422。這不是瀏覽器端自行產生的錯誤,因此前端仍應顯示伺服器訊息。
注意事項
- formula 只接受
expression,不可再帶link_field、aggregation、target_column、required、default_value或max_length。 - Legacy v1 expression 仍為建立時設定;明確的 v2 路徑 可更新
expression、formula_version、computation_mode,仍檢查目前 dependency/rule;formula retype 拒絕。先用 identity-bound update preview,再 PATCH 保留的 body,不必重建 v2 欄位。 - 一般算術只能引用數值輸出。字串與日期欄可和同類輸出比較,也可放進相容的字串/日期函式,但不能當成算術運算元。未 pick 的 cardinality-many lookup 不能作為純量公式輸入;用
pick收斂成單一值的 many lookup 則可以。 IF的條件為null時整個結果為null;AND、OR 與列出的函式也會在任一參數為null時傳播null。- 公式引用會持久化為內部鍵,欄位改名安全;刪除或改型別時,後端會用 409 依賴衝突保護仍被引用的欄位。
試試看
到 API Playground 選擇 columns.preview,先觀察 sample 與結構化錯誤,再把同一份 body 送到 columns.create。