Skip to content

CEL Expression Language

The Computed Column transform evaluates a CEL expression against every row of your dataset. This page documents the expression syntax and the FileBender-specific extensions layered on top of it.

CEL (Common Expression Language) is a non-Turing-complete expression language designed for speed and safety. FileBender uses the @marcbachmann/cel-js implementation, which covers most of the CEL specification.

Expressions are evaluated per-row. Each row is exposed as a flat object whose keys are the column names from your dataset.

There are two ways to reference a column value in an expression:

When a column name is a valid identifier (letters, digits, underscores, starts with a letter), use dot notation directly:

revenue - cost

When a column name contains spaces, punctuation, or starts with a digit, wrap it in square brackets:

[Total Revenue] - [Operating Cost]

FileBender’s preprocessor rewrites bracket references into safe identifiers before the expression reaches the CEL engine. You can mix both styles in the same expression:

[Total Revenue] * tax_rate
OperatorDescriptionExample
+Additionprice + tax
-Subtractiontotal - discount
*Multiplicationquantity * price
/Divisiontotal / count
%Moduloindex % 2

FileBender registers cross-type arithmetic overloads so that numeric CSV columns (parsed as JavaScript floating-point numbers) work naturally with integer literals. An expression like Amount * -1 works even though Amount is a double and -1 is an int.

OperatorDescriptionExample
==Equalstatus == "active"
!=Not equalstatus != "draft"
<Less thanage < 18
<=Less or equalscore <= 100
>Greater thanamount > 0
>=Greater or equalcount >= 10
OperatorDescriptionExample
&&ANDage >= 18 && status == "active"
||ORrole == "admin" || role == "owner"
!NOT!is_deleted
OperatorDescriptionExample
? :Ternaryscore > 50 ? "pass" : "fail"
inMembershipstatus in ["active", "pending"]
FunctionDescriptionExample
string(x)Convert to stringstring(123)"123"
int(x)Convert to integerint("42")42
double(x)Convert to floating-pointdouble("3.14")3.14
type(x)Get the type nametype(42)int
dyn(x)Cast to dynamic typedyn(42)
FunctionDescriptionExample
size(x)Length of list, string, or mapsize("hello")5

These are called as methods on a string value:

MethodDescriptionExample
.contains(s)Substring checkname.contains("Inc")
.startsWith(s)Prefix checkcode.startsWith("US")
.endsWith(s)Suffix checkemail.endsWith(".com")
.matches(regex)Regex matchphone.matches("[0-9]+")
.size()String lengthname.size()
.indexOf(s)First occurrence indextext.indexOf("@")
.lastIndexOf(s)Last occurrence indexpath.lastIndexOf("/")
.substring(start)Slice from indexcode.substring(2)
.substring(start, end)Slice rangecode.substring(0, 2)
MacroDescriptionExample
has(field)Check if a field existshas(row.email)
list.all(x, cond)All elements satisfy conditionscores.all(s, s > 0)
list.exists(x, cond)Any element satisfies conditiontags.exists(t, t == "urgent")
list.exists_one(x, cond)Exactly one satisfiesflags.exists_one(f, f == "primary")
list.map(x, expr)Transform each elementvalues.map(v, v * 2)
list.filter(x, cond)Keep matching elementsitems.filter(i, i > 0)
first_name + " " + last_name
amount > 1000 ? "high" : "low"

If a column might be missing or null, use has() to guard the access:

has(row.discount) ? price - row.discount : price

CSV values are parsed as JavaScript numbers (floating-point). Use int() if you need integer arithmetic:

int(quantity) * int(unit_price)
name + " (qty: " + string(quantity) + ")"

When a CEL expression fails for a given row (type mismatch, division by zero, missing variable), FileBender does not stop the flow. Instead:

  • The failing row’s computed column value is set to null.
  • The row is marked as an error in the execution results.
  • Processing continues with the next row.

This means a single bad row won’t block the rest of your dataset. Check the execution results panel for error counts after running the flow.

  • Expressions are evaluated per-row. You cannot reference other rows or aggregate across the dataset within a single expression. Use Group By for aggregation.
  • The CEL engine runs in the browser. Extremely complex expressions on large datasets may slow down processing.
  • Only the CEL standard library subset shipped by @marcbachmann/cel-js is available. FileBender does not add custom functions beyond the arithmetic overloads described above.