Coda's most powerful formula functions work on lists. Once you understand list processing, you can build rollups, dashboards, and transformations that would require a database in any other tool.
In most spreadsheet tools, a formula operates on one cell at a time. Coda is different — the majority of its powerful formula functions operate on lists: tables, columns, or ranges of multiple values. Understanding whether you're working with a list or a single value (a "scalar") is the key to unlocking Coda formulas and avoiding type errors.
A scalar is a single value: a number, a text string, a date, a checkbox. A list is an ordered collection — a whole table, a filtered subset of rows, or the result of another list-returning function.
thisRow.[Task Name] — the name of one row. Today() — one date. 42 — one number. Functions like Upper(), Len(), and arithmetic operators work on scalars.
Tasks — all rows in the Tasks table. Tasks.[Name] — a column list. Filter() result — a filtered subset. Functions like Count(), Filter(), and Map() work on lists.
Takes a list, returns one value. Count(), Sum(), Average(), Min(), Max().
Takes a list, returns a list. Filter(), Map(), SortBy(), Unique().
Plucks from a list. First(), Last(), Nth(n) — returns a single item, not a list.
Tasks.Filter(...).Count(). If a function returns a scalar, you can't chain a list function after it — that's the source of most "type error" messages in Coda.
Filter(table, condition) returns the subset of rows where the condition evaluates to true. The result is always a list — even if zero or one rows match. You can chain filters, aggregate the result, or use it inside formula columns to create per-row rollups.
// 1. All incomplete tasks Tasks.Filter([Status] != "Done") // 2. Overdue open tasks (chained filters) Tasks.Filter([Status] != "Done").Filter([Due Date] < Today()) // 3. In a formula column on Projects table — tasks for THIS project row Tasks.Filter([Project] = thisRow) // 4. Aggregate the filtered list Tasks.Filter([Project] = thisRow).Count() Tasks.Filter([Project] = thisRow).Sum([Estimate]) Tasks.Filter([Project] = thisRow).Min([Due Date])
| Project Text | Total Tasks Formula | Open Tasks Formula | Overdue Formula | Next Due Formula |
|---|---|---|---|---|
| Website Redesign | 12 | 7 | 3 | Mar 20 |
| Onboarding Flow | 8 | 2 | 0 | Apr 1 |
| Q2 Campaign | 5 | 5 | 1 | Mar 18 |
Tasks.Filter([Project] = thisRow).Filter([Status] != "Done").Count()Tasks.Filter([Project] = thisRow).Filter([Status] != "Done").Filter([Due Date] < Today()).Count()
.First().[Column Name] after the filter. To get a count, chain .Count().
Map() applies a formula to every item in a list and returns a new list of the same length. The placeholder CurrentValue stands in for each item as Map processes the list one element at a time. You can navigate related columns from CurrentValue, concatenate fields, or run any formula that works on a single value.
// 1. Multiply every price by 1.2 (add 20% markup) [Prices].Map(CurrentValue * 1.2) // 2. Build a text label for each task in a relation column thisRow.[Tasks].Map( CurrentValue.[Name] & " (" & CurrentValue.[Status] & ")" ) // → ["Write brief (Done)", "Design mockup (In Progress)", ...] // 3. Chain Filter + Map: names of open tasks for this project Tasks.Filter([Project] = thisRow).Map(CurrentValue.[Name]) // → ["Write spec", "Review designs", "Update docs"]
Map always returns a list the same length as the input. 10 rows in, 10 values out. This makes it predictable — unlike Filter(), which can shrink the list.
Think of CurrentValue as "this item in the loop." When the list is a table's rows, CurrentValue.[Column] accesses that row's field.
Tasks.Filter([Project]=thisRow).Map(CurrentValue.[Name]).Join(", ") — the Join() function collapses a list to one delimited string.
Reduce() walks through a list and accumulates a running result. It takes two arguments: an initial value (where the accumulator starts) and a formula combining Accumulator (the running result so far) with CurrentValue (the current item). Reduce is the general-purpose tool — Sum(), Count(), and even Join() are all special cases of Reduce.
// 1. Sum prices explicitly (same as Sum() but transparent) [Prices].Reduce(0, Accumulator + CurrentValue) // 2. Join names with commas, handling the empty-first-item edge case [Names].Reduce("", Accumulator & If(Accumulator = "", "", ", ") & CurrentValue ) // → "Alice, Bob, Carol" // 3. Count done tasks (alternative to Filter + Count) Tasks.Reduce(0, Accumulator + If(CurrentValue.[Done], 1, 0) )
[Names] — a list column or any list expression
Reduce() — folds the list to one value using an accumulator
"" — start with an empty string; accumulator begins here
If(Accumulator = "", "", ", ") — skip the comma on the very first item
Filter().Count() is clearer and more readable. Use Reduce() when you need a custom accumulation that no built-in aggregation function provides — like building a comma-joined string, a weighted score, or a conditional running total.
After filtering and transforming a list, you often need to sort it, remove duplicates, or extract specific items. These functions compose naturally with Filter() and Map() — each takes a list and returns a list or a single value.
// Sort tasks by due date ascending (true = oldest first) Tasks.Filter([Project] = thisRow) .SortBy([Due Date], true) // Sort descending — most recent first (false = newest first) Tasks.Filter([Status] = "Done") .SortBy([Completed], false) // Most recently completed task — single row result Tasks.Filter([Status] = "Done") .SortBy([Completed], false) .First() // Second item in a sorted list Tasks.SortBy([Due Date], true).Nth(2) // Deduplicate: all unique tag values across all task rows Tasks.[Tags].Unique()
Returns the list sorted by the key formula. true = ascending (A→Z, 1→9, oldest first). false = descending.
Pluck one item from a list. Returns a scalar — the actual row or value, not a list. Chain .First().[Column] to get a field from the first row.
Returns the list with duplicates removed. Useful for tag clouds, category counts, or ensuring exactly one reference per item.
The true power of Coda's list functions appears when you compose them together. A single formula column can summarize hundreds of task rows into a human-readable status line — no pivot table, no external report, no manual update needed.
Tasks.Filter([Status] != "Done").Count() — all tasks not yet done
.Filter([Status] != "Done").Filter([Due Date] < Today()) — chained filters narrow to overdue open tasks
Filter([Completed] >= DateAdd(Today(),-7,"days")) — tasks completed in the last 7 days