Real spreadsheets, built in.
Price the job in a live worksheet beside your drawing — it fills itself from your measurements, cost databases and formulas. No bouncing to Excel to estimate.
It prices as you measure.
// liveDrop a measurement and the row fills in — quantity, rate, line total, and the job total, all live.
- Measure on the drawing — areas, lengths, counts.
- The row fills in — quantity in, rate from the database, line total out.
- The job total moves the instant you drop a measurement.
Familiar as Excel.
The gestures and the core functions you actually reach for — plus one-click export to Excel (.xlsx) whenever you need it.
- Type, edit & fill-down
- Drag to extend a formula
- Default column formulas
- Copy-paste — in and out of Excel
- ~50 core functions (SUM, IF, VLOOKUP…)
- Cell & number formats
- Multiple sheets
- Export to Excel (.xlsx)
Any sheet is a database.
Nothing's a fixed template. Flag a key column on any sheet — rates, assemblies, crews, waste factors, supplier lists — and look its values up from anywhere by key. You build the model; the sheet does the arithmetic.
So a priced line is just a formula you write. For instance:
Quantity
Area, perimeter, volume — and every tag — always on the row.
A looked-up value
A rate, an assembly, a crew — pulled by key from a sheet you choose.
Line total
Recomputes the instant either side changes.
Pull from as many databases as you like, combine them however the estimate needs — then scope a total across the whole project.
Power Syntax.
// estimating-nativeThe Excel functions you reach for, plus a handful built for estimating.
database.cost([item]) * [quantity]→Prices each measurement from your live database.SUM.project([:cost])→Auto-prices the entire job, across every sheet.SUM.discipline=concrete([:volume])→Totals just the concrete, project-wide.SUM.building=3([:cost])→Totals one building without touching the others.Rates.rate([type])→Looks up a rate from another sheet, by type.The full syntax
Named cells and columns, cross-sheet lookups, and project-wide scoping — the whole language.
| What | Example | What it means |
|---|---|---|
| Named cell | [area] | The area cell on this row — referenced by name, so templates don't break when columns move. |
| Whole column | [:area] | The entire area column — same as A:A, but for named columns. |
| Cost lookup | database.cost([item]) | Pulls a unit price from your live cost database, matched by item. |
| Cross-sheet lookup | Rates.rate([type]) | Reads a value off another sheet, matched by key — like a named VLOOKUP. |
| Project-wide total | SUM.project([:cost]) | Totals a column across every sheet in the set, not just this one. |
| Scoped total | SUM.discipline=concrete([:volume]) | Totals only what matches the tag — swap in building=3, level=2… |
| Core Excel functions | SUM · IF · VLOOKUP · SUMIF | Around 50 of the Excel functions you actually reach for, unchanged. |
Purple Hammer's worksheet supports a fixed, enumerated set of 50 built-in functions plus estimating-native Power Syntax: column references that survive renames and reordering, sheets that act as callable lookup tables, cross-sheet references, and scoped aggregates that total across the whole project. The complete syntax is listed below, deliberate limits included, mirrored from the in-app reference.
Full detail — functions, syntax, interchange, limits
The 50 built-in functions
SUM · IF · ROUND · FLOOR · CEILING · MIN · MAX · AVERAGE · COUNT · CONCAT · VLOOKUP · XLOOKUP · HLOOKUP · INDEX · MATCH · IFERROR · SUMIF · COUNTIF · AVERAGEIF · SUMIFS · LEFT · RIGHT · TRIM · ABS · SQRT · MOD · ROUNDUP · ROUNDDOWN · INT · MROUND · POWER · SUMPRODUCT · COUNTIFS · AVERAGEIFS · MID · LEN · UPPER · LOWER · SUBSTITUTE · FIND · TEXT · VALUE · TEXTJOIN · IFS · SWITCH · IFNA · ISBLANK · ISNUMBER · TODAY · AGGREGATE
The set is fixed and enforced. An unknown name returns #NAME?; a wrong argument count returns #VALUE! — never a silent guess.
References
Classic A1 style works as expected, with absolutes and ranges (A1, $A$1, A1:C4). Named references bind to a column's identity, not its label or position, so formulas survive renames and reorders.
[column] is this row's cell; [:column] is the whole column; [@column] is accepted as the Excel-paste alias; [:"line item cost"] quotes names with spaces. Cross-sheet references (Sheet1!A24) cover cells, ranges and whole columns.
Lookup sheets
Any sheet can be promoted to a lookup table with a key column, then called like a function:
Rates.rate("concrete")— by literalRates.rate([type])— per rowRates.rate(A3)— by cellRates.rate()— the whole columnRates["expected quantity"](key)— spaced column names
Scoped aggregates
Thirteen of the fifty accept scope modifiers: SUM, MIN, MAX, AVERAGE, COUNT, SUMIF, COUNTIF, AVERAGEIF, SUMIFS, SUMPRODUCT, COUNTIFS, AVERAGEIFS, AGGREGATE.
Reserved scopes: .this (home sheet, the default), .project (every sheet), .live (drawing-bound sheets), .orphan (custom sheets). Field predicates filter by tag — SUM.building=3([:cost]), SUM.discipline=concrete([:volume]) — and chain as AND: SUM.live.discipline=concrete(…).
Scopes compose with per-row lookups. SUM.floor=3([:quantity] * Rates.rate([type])) prices one floor of the whole project in a single cell.
Arrays & broadcast
Whole-column references broadcast through + − × ÷ ^. One formula computes the entire column, replacing fill-down. A column can also carry a default formula that stamps itself onto every new row.
Formats & locale
Per-column display formats: normal, currency, percentage, with configurable decimals. Formula text is locale-neutral; the display follows your locale, with European (1.234,56), UK and US number and date conventions supported.
Excel interchange
Copy-paste works in both directions. CSV import auto-detects US and EU number styles.
Excel (.xlsx) export rewrites Power Syntax into standard Excel, so the workbook keeps calculating after export: named references become A1 references, lookup calls become XLOOKUP, and project-wide totals become per-sheet sums.
Deliberately not supported
Wildcards (*, ?) in SUMIF-family criteria; AGGREGATE beyond sum/average-ignoring-errors; INDEX whole-row/column slicing; array literals like {1,2,3}; broadcasting through comparisons or &.
There is no declared row or column cap. Sheets are bounded by data and performance, not a grid constant.
Stop bouncing to Excel.
The takeoff and the estimate, in one live sheet. Free 30-day trial.