Formula language
Partly availableSome of what this page describes is in DimSum today and some is still coming. Parts marked Coming are designed but not built yet.
Excel-like formulas with DimSum's own `{property}` references, a click-to-insert Property Picker, unit awareness, a live result and loud red ERRORs, used on any property of an item, a part or the job.
Overview
Formulas turn measurements into material and labor. any property of an item, a part or the job can be a formula: a part's Qty, its Enabled switch, its Price Each, its SubDivision, your own Ext Cost, a job's Labor Rate. A property's Input Condition (when its row shows) is a formula too.
If you've used Excel, the working half of a formula is the half you already know: ROUNDUP, IF, IFS, SUM, CONCAT, + − × ÷, %, the comparisons. None of that changed and none of it is ours to invent. What is ours is how a formula names a value: in braces, with > for "inside" — {Height}, {Item > Linear Total}, {Parent > Plates > Qty}. On top of that:
- Property Picker: a button in the formula toolbar. Click where from, click the property, and the right reference is typed at the cursor.
- Units: every property has its own unit, so feet × feet gives square feet and feet ÷ inches gives a plain count. Units that don't make sense give an amber warning, not an error, and you can turn unit handling off per formula.
- Loud errors: a broken formula shows ERROR in big bright red wherever the value appears, and lands in Needs attention.
- Rename-safe, capital-blind references: rename a property or a part and every formula and Input Condition follows;
{qty}works the same as{Qty}. - Decision tables Coming.
- Construction functions Coming:
PITCHFACTOR,ROUNDTO(named rounding presets like "Nearest 2 ft"),STOCKLENGTHandMATCH. - Safety: formulas are pure calculations. They can't read files or reach the network.
Round Up is gone. If you used the checkbox put the rounding into the formula; a job that still has it opens clean and the rows go. The
ROUNDUP()function is unchanged.
Where to find it
| Where | Status |
|---|---|
| fx on any row of the Properties panel: item, part, and the part editor | |
| fx on a Job property in Project Settings | |
| Input Condition in + Add property and Settings… (when a property's row shows) | — see Property System |
| Tools tab → a tool → Properties and Parts tabs | — the same fx editor and toolbar as a job, with its live result, the Property Picker, Condition… and Text…. *Earlier versions of this page said the result line and the Picker were blank in the designer; that was an empty state misread, and both have worked * |
| Tools tab → a tool → Playground | — draw with the tool itself on the Playground sheet, and every formula on it and its parts follows the drawing |
| Condition… and Text… on every formula toolbar | — the Condition Builder and text templates |
| Tool Settings dialog → Advanced (right-click an item → Settings…) | — every property with its fx, and the one place an item's Name has one |
| A tool's label (e.g. the Beam label) | — a text piece fills {fields}, and a piece that starts with = is one formula (Tool Designer → the Label tab). Since 0.5.30 a bare {field} reads in its property's own format (Mark # 1, Plies 2), while a whole = formula keeps the formula preview's style. Text boxes and stamps: Coming |
| Report fields, filters and column formulas (Report Designer) | a report column can be a formula over fields — the Test Report's Extended is {Part > Qty} * {Part > Cost Each} — with + - * / and brackets; a blank field gives a blank answer, and an ERROR field, a word or a division by zero gives ERROR. the Report Designer shows a column's formula. a report's filter (Only rows where… → Advanced), a column's Formula and a totals table's filter are typed as report expressions |
| Assembly layer thickness, constraints and Qty (Assemblies) | Coming |
An Advanced Part's filters — List Matching as a kind of part (Dynamic Lists → The Advanced Part). A filter's Input is a property — the part's, its tool's or the job's — picked with this same Property Picker, or a value you type; its Only when is a condition formula — {Stud Size} <> "". In the picker, an Advanced Part's input reads This item › Height, This part › … or The job › …, and a property the match itself writes is refused. The matched columns are the part's own properties, read like any other: {Cost Each} | |
Vertex elevations ({Level > Elevation} + {Plate Height}) | Coming |
| Estimating tab cells (inline, spreadsheet-style) | Coming |
A field becomes a formula with the fx button. A leading = is allowed and ignored (=1+2 is 1+2).
How to use it
Write a formula with the fx editor
- Click fx on the value you want to calculate, e.g. the Qty of a Subfloor Glue part. (Or right-click the row → Use a formula (fx).)
- The editor opens under the row: a toolbar, the formula box, a result line, an Ignore units box, and Apply / Cancel.
- Click Property Picker, click where from (Parent (Subfloor 3/4" T&G)), then click Qty.
{Parent > Qty}is typed at the cursor. the tool, named, with its parts nested inside it as deep as they go and the one you are on opened and highlighted, then Page, Level, Job, Table and Material — so a sibling or a part two levels down is two clicks, and what it types is the same reference it always was. - Use the toolbar for the rest: + − × ÷ insert an operator; ROUNDUP wraps what you selected in
ROUNDUP(…, 0); IF wraps it inIF(…, , ). Or just type:ROUNDUP({Parent > Qty} / 4, 0). - The result line updates as you type (a moment after you stop) and shows 11. It is the core's own answer, the same one the part row and the Estimating tab will show.
- Press Enter or Apply. Esc or Cancel leaves the formula as it was. Emptying the box and applying clears the formula back to the default.
The preview shows the formula's own result and unit. Once applied, the result goes into the property's unit (a Qty into its Qty Unit), so {Item > Qty} may preview as 100' and then show as 100.00 on the row (a Qty shows no count unit, and the System Settings decimal places).
Type a formula (power users)
Type it straight into the box. Function names and AND / OR / NOT / TRUE / FALSE work in any capitals. Spaces and new lines are free.
- a formula that doesn't parse shows ERROR with the reason, and a red caret line under the exact place it went wrong:
ROUND(1 2)
^
ERROR Expected , or ) but found '2'A broken formula is still saved when you apply it. It shows ERROR everywhere until you fix it, because half a formula at 4 pm shouldn't be lost.
The Condition Builder
IF, IFS and SWITCH without counting commas. All three were already in the language; the builder writes them for you and shows you what it wrote.
- Open fx on the row and click Condition… on the toolbar.
- Pick the shape: Tests — If / Else if rows, each a test and a value, first true one wins — or Match one value against a list of values (that is
SWITCH). - Fill the rows. + adds another test; × on a row takes it away; Otherwise is the answer when nothing matches. The Property Picker at the foot puts a reference into whichever box you were last in, and says which.
- The formula it will write is shown underneath, in the box's own lettering. Apply puts it in the formula box, and from there it is applied like any formula you typed.
| Rows | What it writes |
|---|---|
| One test and an Otherwise | IF(test, then, otherwise) |
| Several tests | IFS(t1, v1, t2, v2, …), with TRUE, otherwise last when there is an Otherwise |
| One value matched against several | SWITCH(value, m1, v1, …, otherwise) |
It only reads back what it can write back unchanged. Open the builder on a formula it wrote — or one you typed in the same shape, spaces and all — and you get the rows back, and applying them gives the same formula, character for character. Open it on anything else — say MAX(IF({A} > 1, 2, 3), 0) — and it will not guess at the IF in the middle. It says "This is not a plain condition, so the builder cannot show it without changing it", shows the formula, and offers Replace it. Nothing changes until you press that; Cancel leaves the formula exactly as it was.
Example 17 below is the kind of formula it writes.
Name formulas and text templates
A name can be a formula, so an item is called 2x6 @ 16" O.C. because of its own properties, and changes when they do. You don't write the formula — you type the name the way you want to read it, with the values in braces, and Text… writes the formula for you.
- Open the Name row's fx. For an item, that row is in the Tool Settings dialog → Advanced (right-click the item → Settings…), because the Properties panel shows Name as a heading, not a row.
- Click Text… on the toolbar and type the template:
2x{Nominal Depth} @ {Stud Spacing}" O.C.- The live result shows underneath —
2x6 @ 16" O.C.— and so does the formula it will write:
CONCAT("2x", {Nominal Depth}, " @ ", {Stud Spacing}, """ O.C.")- Apply. The name now follows: change Stud Spacing to 24 and the item is called
2x6 @ 24" O.C.— on the canvas label, in the Project Tree, the Takeoff list and the Estimating tab, not only in the panel.
Three rules for braces in a template, and that is all of them:
- Inside braces is a reference, and only a reference — the same
{Item > …},{Parent > …},{Table > …}spelling as everywhere else.{TODAY()}is not a function call; it reads as a property called TODAY and says there is none. Anything cleverer than a reference goes in the formula, one click away in the same box. {{is a literal{and}}is a literal}. A name may never contain a brace, so doubling is the one escape needed.- Everything else is text, spaces and inch marks included. The
"in16" O.C.needs no escaping; the builder doubles it in the formula, because that is how a formula reads a quote inside text.
It is on every formula box, not only Name — a Description, a custom Text property, anything. Name is simply the one that needed it: a table refuses to set a Name ("naming something from its own values is what Name formulas do"), and this is where that sentence points.
It reads back only what it can write back unchanged, the same rule as the Condition Builder: CONCAT("a", {B}) opens as a{B}, but CONCAT("a", UPPER({B})) does not open as a template at all — you are offered Replace it rather than having the UPPER quietly dropped.
Numbers join without their units. {Height} in a name reads 9, not 9 ft or 9'-0". A name that wants the unit spells it: {Height} ft.
When the answer can't be a name, the name stays as it was. On a part, an answer that is blank, ERROR, contains {, } or >, or is the name of a sibling part is not used — a duplicate would make {Parent > Studs > Qty} name two parts — and the part keeps the name it had, on the drawing and in every list. The panel shows the same thing, so the two never disagree. Two items called Ext Wall is fine; item names have no such rule. Renaming by formula carries the same rename safety as typing a new name: formulas that name the part follow it.
Replace dozens of IFs with a decision table
Coming A Dynamic List used as a rule table (e.g. Stud Length Rules: Wall Height, Plate Count, Stud Length), read withMATCH() and {Match > Stud Length}. Change a rule by editing a row, not a formula. For a part, the Advanced Part does this without a formula: make the rules a Material Library table and filter it — Wall Height equals {Item > Height} — and the row it leaves fills the part (The Advanced Part).Test a formula before using it
in a job, the result line shows the answer against the real item as you type, and nothing is stored until you apply.
Test a whole tool: the Tools Playground
A tool is formulas all the way down, and none of them mean anything until something is measured — so the Tool Designer lets you measure something. Open the Tools tab, open a tool, click Playground, and draw with it on the blank sheet: every formula on the tool and on its parts follows the drawing, from the same engine a job uses. Edit a formula and the Playground changes with it, because a tool there is linked, not copied.
The Test Bench's sample boxes are still there, under the sheet, for a tool nobody wants to draw with — they hand over and grey out once something is drawn:
- Sample fields: Linear Total (ft), Runs, Area (SF), Perimeter (ft), Openings, Count and Height (ft). Change one and every number below it moves.
- A field that isn't one of that tool's measurements is greyed, with the reason: "Ext Wall 2x6 is a linear tool, so this is not one of its measurements." Height is typed on the item whatever the tool, so it is never greyed.
- Standard sample puts the sample back to 100 ft / 1,000 SF / 10 (height 8 ft). It is greyed while the sample is already the standard one.
- Underneath: a table of every property with its result, then every part with its Qty, with errors highlighted. On the standard sample,
Ext Wall 2x6 (example)reads 76.00 studs. - The numbers are the core's, so they are exactly what the item will say once the tool is placed. The sample is remembered per tool.
There are no Material $ / Labor / Total columns: no money is built in, so a cost is a property like any other and shows in the property table. Runs, Perimeter and Cutouts are not among the bench's own fields.
See Tool Designer.
Find and fix broken formulas
- A broken formula shows ERROR in big bright red on the row, the part row, the Takeoff list and the Estimating tab. Hover it for the reason.
- The status strip shows 3 need attention when anything in the job is in ERROR or has a warning. Click it, or open the Estimating tab: the Needs attention (3) list is at the top, with n ERRORS · n warnings.
- Each row reads: ERROR (or Warning) · where (
Ext Wall 2x6 › Plates) · which property · why. Click it: DimSum switches to Takeoff, selects the item, shows its sheet and opens the part. - Two formulas that read each other show the cycle: "Circular: A → B → A". On parts it names both: "Circular: Plates.Qty → Studs.Qty → Plates.Qty". Change one so it no longer refers back.
- Reports warn at the top but still run: on the Reports tab an ERROR value prints ERROR in red, the totals leave it out and say how many, and a note above the preview counts them.
Options & settings
How a reference is written
A reference goes in braces, and > means "inside". Read it left to right: Parent, then Plates, then Qty.
| What you want | Write | Reads as |
|---|---|---|
| A property on this item or part | {Height}, {Qty} | Height, here |
| A property on the item this part belongs to (or the item referring to itself) | {Item > Linear Total} | the Item, then Linear Total |
| The part above this one (the item, for a top-level part) | {Parent > Qty} | Parent, then Qty |
| Two levels up | {Parent > Parent > Qty} | Parent, Parent, then Qty |
| A sibling part, by name | {Parent > Plates > Qty} | Parent, Plates, then Qty |
| A child part, by name | {Studs > Qty} | Studs, then Qty |
The direct child parts, inside SUM / COUNT / AVG / MIN / MAX | SUM({Children > Labor Hours}), COUNT({Children}) | Children, then Labor Hours |
| The job: its name, number, customer and your own Job properties (Project Settings) | {Job > Labor Rate}, {Job > Job #} | the Job, then Labor Rate |
| The item's home sheet and its group | {Page > Sheet}, {Page > Scale}, {Level > Name}, {Level > Elevation} | the Page, then Sheet |
| A column of the table row this item or part follows | {Table > Framing > Stud Spacing} | the Table Framing, then Stud Spacing |
| A field of the part's linked material | {Material > Cost} | the Material, then Cost |
The eight words are ours: Item, Parent, Children, Job, Page, Level, Table and Material. Not "Tool", not "Project".
Tablenames the table and the column, never the row. The row is whichever one the item or part was Set from a table… with, so picking a different row re-reads every{Table > …}on it at once.With nothing linked it reads blank, with a small warning — the amber mark, "no material linked" on hover, and a warning in Needs attention.
Parentrepeats, once per level up:{Parent > Parent > Qty},{Parent > Parent > Parent > Qty}.Spaces around
>are yours to like or not.{Parent>Qty}and{Parent > Qty}are the same reference. DimSum always writes>, with the spaces.Capitals don't matter anywhere:
{qty},{Qty}and{item > o.c.}all work. A name keeps the capitals you typed.A word is only a word where it can be one.
Item,Job,PageandLevelare the first step or nothing;Childrenis the first step, and only insideSUM,COUNT,AVG,MINorMAX;Parentis a leading run of steps. So a property of your own genuinely called Parent is reached as{Item > Parent}, or as a bare{Parent}on something with nothing above it.Between the braces, a name can hold almost anything — spaces, dots, percent signs, slashes, quote marks,
#,&.{O.C.},{Slack %},{Parent > Subfloor 3/4" T&G > Qty},{Job > Job #}all read cleanly. The only three characters a name may not contain are{,}and>, and DimSum refuses to save a property or part named with one, saying which character and why.
Why braces
Because your property names are the awkward part, not the formulas.
- Braces were free. DimSum has no array literals, so
{and}meant nothing else in a formula. Nothing clashes. >reads as "inside"...\read like a Windows folder, because it was borrowed from one.- It dodges the names you actually use. A
/separator fights Subfloor 3/4" T&G. A.separator fights O.C. No delimiter at all fights every name with a space in it, which is most of them — Linear Total, Slack %, Opening Width Total. A>appears in none of them, which is exactly why it can be the one character that means something. - And it is DimSum's. Our own — for references. Excel keeps the rest.
Your old jobs are rewritten for you
Nobody retypes a formula. Opening a job or a tool written before this change runs a one-time migration that rewrites every stored formula, Qty default and Input Condition into braces. After one open, every reference in the file is spelt the one way this page teaches — the Picker's way, and the way a rename gives back.
Syntax
| Element | Syntax | Example |
|---|---|---|
| Property reference | {Name} or {Word > Name} (capitals don't matter; spaces around > are optional) | {Area}, {Item > Linear Total}, {level > name} |
| Old names (aliases) | {Linear Total}, {Count}, {Segments} and {Created At} still work. The Picker writes the new names: {Linear}, {Point Count}, {Segment Count}, {Time Stamp} (Property System) | {Item > Linear Total} = {Item > Linear} |
| Parent / relative | {Parent > Name}, {Parent > Parent > Name}, {Parent > Sibling > Name}, {Child > Name} | {Parent > Qty}, {Parent > Plates > Qty}, {Studs > Qty} |
| Children | {Children > Name} inside SUM, COUNT, AVG, MIN, MAX; COUNT({Children}) | SUM({Children > Labor Hours}) |
| Numbers | 12, 0.5, .5, 1.5e3 | |
| Percent | 10% (= 0.10) | {Area} * (1 + 10%) |
| Text | double quotes; "" for a quote inside | "Ext Wall", "3/4"" ply" |
| Booleans | TRUE, FALSE | IF({Treated} = TRUE, …) |
A leading = | ignored | =ROUNDUP({Qty}, 0) |
Lengths typed with ' and " | Not in formulas yet. 10' + 2 shows ERROR: "Unit marks like 10' are not supported yet: put the number in a property that has a unit". Type lengths into a Number property whose unit is ft or in, and reference it; a bare number next to a length takes its unit ({Item > Height} > 8 means 8') | Which build brings unit marks is to confirm |
| Text templates | Written in the Text… builder, not in the formula: {Level > Name} – {Name} becomes CONCAT({Level > Name}, " – ", {Name}) | — see Name formulas and text templates. Inside a formula, a reference inside quotes is still plain text |
Operators
| Operator | Meaning | Example |
|---|---|---|
+ - * / | Arithmetic | {Linear Total} * {Height} |
^ | Power (right to left: 2^3^2 = 512; -2^2 = −4) | {Rise} ^ 2 |
% | Percent, written after a number: 15% = 0.15. It is not remainder — use MOD() | 200 * 15% → 30 |
= <> < <= > >= | Comparisons. Text compares without regard to capitals. They can't be chained: use AND(a < b, b < c) | {Qty} > 0 |
AND OR NOT | Logic, as words between values or as functions | {Treated} AND {Qty} > 0 |
& | Join text | {Level > Name} & " Walls" |
Order, tightest first: %, ^, unary minus, * /, + -, &, comparisons, NOT, AND, OR.
Functions
| Function | What it does | Example | Result |
|---|---|---|---|
| Rounding | |||
ROUND(value, digits) | Round to a number of decimals (digits optional, default 0; halves away from zero; negative digits round to tens) | ROUND(4.3575, 2) | 4.36 |
ROUNDUP(value, digits) | Always round up (away from zero) | ROUNDUP(42.8, 0) or ROUNDUP(42.8) | 43 |
ROUNDDOWN(value, digits) | Always round down (toward zero) | ROUNDDOWN(42.8, 0) | 42 |
CEILING(value, step) | Up to a multiple of step (a step in other units is converted) | CEILING(15.56, 0.5) | 16 |
FLOOR(value, step) | Down to a multiple of step | FLOOR(15.56, 0.5) | 15.5 |
| Math | |||
ABS(x) | Absolute value | ABS(-3) | 3 |
MIN(a, b, …) / MAX(a, b, …) | Smallest / largest (units converted to the first) | MAX({Height}, 8) | the larger |
SQRT(x) | Square root; of an area it gives a length (144 sf → 12') | SQRT(1 + (6/12)^2) | 1.118 (shown as 1.12 at the default 2 decimals) |
PI() | π | PI() * {Radius}^2 | circle area |
MOD(a, b) | Remainder (takes the sign of b) | MOD(10, 3) | 1 |
| Logic | |||
IF(test, then, else) | Choose between two values. Without an else, a false test gives FALSE (0 in a number) | IF({Treated}, "PT", "SPF") | |
IFS(test1, v1, test2, v2, …) | The first value whose test is true. End with TRUE, value for a default; with no true test it is ERROR | IFS({H} > 10, "tall", {H} > 8, "mid", TRUE, "short") | mid |
SWITCH(expr, case1, v1, …, default) | Match a value against cases (text ignores capitals; lengths convert) | SWITCH({Size}, "2x4", 3.5, "2x6", 5.5, 0) | 5.5 |
AND(…), OR(…), NOT(x), TRUE(), FALSE() | Logic as functions | AND({Treated}, {Qty} > 0) | |
| Aggregates | |||
SUM(…) | Total. Takes {Children > X}; blanks skipped; no children = 0 | SUM({Children > Qty}) | |
COUNT(…) | How many non-blank values | COUNT({Children}) | number of child parts |
AVG(…) (also AVERAGE) | Average, blanks skipped | AVG({Children > Qty}) | |
| Text | |||
CONCAT(a, b, …) | Join text | CONCAT({Size}, " ", {Species}) | "2x10 SPF" |
LEFT(t, n) / RIGHT(t, n) | First / last n characters (default 1) | LEFT({Item #}, 3) | "210" |
MID(t, start, n) | n characters from start (1 = first) | MID("2x6x12", 3, 1) | "6" |
UPPER(t) / LOWER(t) | Change case | UPPER("osb 7/16") | "OSB 7/16" |
LEN(t) | Number of characters | LEN("T&G") | 3 |
IF, IFS, SWITCH, AND and OR short-circuit: they only work out the branch they take, so IF({Qty}=0, 0, 100/{Qty}) never divides by zero. But the whole formula is checked before anything runs, so an unknown function or a wrong argument count is ERROR even in a branch that isn't taken — a typo can't hide until the day the other branch is used.
Rounding ignores floating-point noise: 1,600 sf × 1.10 ÷ 32 is 55.00000000000001 inside the computer, and ROUNDUP gives 55, not 56.
Functions not built yet
Each one shows ERROR saying when it arrives, e.g. "ROUNDTO is not available yet. It arrives with the Behind the scenes tables ."
| Function | What it will do | Example | Arrives |
|---|---|---|---|
SUMIF(values, condition), COUNTIF(…) | Total / count where a condition is true, across items | SUMIF({Tools > Qty}, {Tools > Name} = "Ext Wall") | No build named |
LOOKUP(list, key, column) | One value from a Dynamic List row | LOOKUP("Lumber", "2x6 PT", "Price") | No build named |
MATCH(list, col1, val1, …) | The row meeting all criteria; fields read as {Match > Column} | MATCH("Dimensional Lumber", "Nom. Width", 2, "Nom. Depth", 10, "Length", 12) | No build named |
ROUNDTO(value, "Preset") | Round with a named row of the Rounding Presets table | ROUNDTO(11.33, "Nearest 2 ft") → 12' | Coming |
STOCKLENGTH(length, "Stock list") | The next stock length at or above length | STOCKLENGTH(13.17, "Dimensional") → 14' | Coming |
PITCHFACTOR(pitch) | Factor from the editable Pitch Factor table | PITCHFACTOR("6/12") → 1.118 | Coming |
PITCH(rise, run) | Build a pitch | PITCH(6, 12) → 6/12 | |
CONVERT(value, "from", "to") | Convert units | CONVERT(400, "cu ft", "cu yd") → 14.81 | |
FEET(x) / INCHES(x) | Treat a plain number as feet / inches | FEET(10) → 10' | |
TEXT(value, "format") | Format a number as text | TEXT({Qty}, "0.00") | |
TODAY() | Today's date | ||
SIN COS TAN ASIN ACOS ATAN ATAN2 | Trig | (degrees or radians to confirm) |
About the construction functions Coming
PITCHFACTOR(pitch)will read the Pitch Factor table in Behind the scenes. Factory defaults are √(1 + (rise/12)²) to 3 decimals (4/12 → 1.054, 6/12 → 1.118, 8/12 → 1.202, 12/12 → 1.414). Edit 6/12 to 1.116 and new projects use 1.116.ROUNDTO(value, "Preset")will name a row of the user-extendable Rounding Presets table: name + increment + direction (Up / Nearest / Down) + unit. It ships with None; Nearest 1/16", 1/4", 1/2", 1"; Nearest 1 cm; Nearest 0.5 ft, 1 ft, 2 ft, 10 ft, 20 ft; Up to next 1 ft, 2 ft (even), 10 ft; Up to stock length. A missing preset name will show ERROR.STOCKLENGTH(length, "List")will read a stock length list (Dimensional = 8' to 24' in 2' steps; LVL to 60'; conduit 10'…).MATCH(…)would give a formula the power a part gets from the Advanced Part — *no build named *.
Report expressions
). The Report Designer has its own small expression language, for three places: a report's filter (Only rows where… → Advanced), a column's Formula, and a totals table's filter. It is written the way a formula is, so what you know here carries over:
{Part > Division} = "06 Wood, Plastics, and Composites" AND {Part > Qty} > 0
{Part > Qty} * {Part > Cost Each}| A formula (this page) | A report expression | |
|---|---|---|
| What it's on | A property of an item, a part or the job | A report: which rows print, and what a column shows |
| What it can read | Its own item, the item's parts, its sheet and level, the job — {Height}, {Parent > Qty}, {Job > Labor Rate} | One report row's fields, named as the report's field list names them — {Part > Qty}, {Item > Sheet}, {Job > Name}. No {Parent > …} or {Children > …}: the job's formulas have already worked those out |
| References | In braces, > for "inside" | The same |
| Operators | + - * /, ^, %, = <> < <= > >=, AND OR NOT, & | + - * / (× and ÷ too), brackets, the same comparisons (!=, ≠, ≤, ≥ too), AND OR NOT, & — no ^ or % |
| Functions | The full list above | IF, ISBLANK, ROUND, ROUNDUP, ROUNDDOWN, ABS, MIN, MAX, and AND / OR / NOT as functions. Adding up is a column's Total (Sum, Count, Average, Smallest, Largest), not SUM() |
| Blanks | 0, empty text or FALSE, as in Excel | The same in a filter. In a column's formula, arithmetic with a blank is blank — + - * /, a leading minus, and ROUND, ROUNDUP, ROUNDDOWN, ABS, MIN, MAX given a blank — so a missing price is a gap, never 0.00; ISBLANK, IF, AND / OR / NOT, comparisons and & work as usual. A blank cell counts as 0 in the column's sums |
| ERROR | Big red ERROR, listed in Needs attention | Carries through: anything worked out from an ERROR is ERROR, printed red, and left out of the totals |
| Mistakes | The red caret line under the place it went wrong | Shown as you type, in plain words, with where |
| Changes the job? | Its answer is the property's value | Never — a report only reads |
A report expression is worked out by the report as it lays out its rows; the values it reads are the ones this page's formulas already worked out, so a report and the Estimating tab agree. Want a value kept on the part itself, to see on the Estimating tab too? Give the part's property a formula here, then print that field in the report.
Rows that take no formula
A part's unit takes no formula. It names what the Qty is counted in (ea, sheet, cy, hr), and that is not something to work out.
Do the maths in the Qty and leave the unit alone. Other rows that can't take a formula are listed under Rules, limits & edge cases.
Where a formula sits on a tool
A formula in the Tool Designer is written in the same fx box as a job's, and it sits beside the rest of a real property: the row it is on carries its own hint, its unit, decimal places, input condition, list, Input tick, Hidden and Locked, all on Settings…. a tool property carried only a name, a type and a first value, so a formula there had nothing around it.
Both were there — the result line is blank until you type, the Picker blank until you open it, and those empty states were written up as missing features for two builds. A part's ROUNDUP({Item > Linear Total} * 12 / 16, 0) + 1 reads = 76 under the box on the standard sample, with the caret on a bad token, exactly as in a job.
A part's classifications follow its parent
Division, SubDivision, Construction Phase and Trade resolve up the tree: this part's own value, then the part above it, then the item, then blank. So {Division} on a part can answer with the item's Division, and a nested part can answer with the part above it.
| What you do | What the part shows | What a formula reads |
|---|---|---|
Leave it blank, item Division = 06 Wood & Plastics | 06 Wood & Plastics in grey, "from Ext Wall 2x6" on hover | 06 Wood & Plastics |
Type 09 Finishes on the part | 09 Finishes in black | 09 Finishes |
| Clear it again | back to grey, from the item | the item's value |
| Nothing above it has one either | blank | blank (empty text) |
Typing your own value stops that one property following; clearing it makes it follow again. Only those four classifications inherit — everything else on a part starts blank and stays blank, so a part's Cost Each never comes from the item.
Examples
Every number below is worked out so you can check it by hand. Each example says whether it works
1. Floor sheathing with nested parts (framing) — works
Area item Floor Sheathing, Area = 1,245 sf.
| Part | Qty formula | Working | Result |
|---|---|---|---|
| Subfloor 3/4" T&G | ROUNDUP({Item > Area} * 1.10 / 32, 0) | 1,245 × 1.10 = 1,369.5; ÷ 32 = 42.80 → up | 43 |
| └ Subfloor Glue (child) | ROUNDUP({Parent > Qty} / 4, 0) | 43 ÷ 4 = 10.75 → up | 11 |
| Nails 8d | ROUNDUP({Item > Area} / 500, 0) | 1,245 ÷ 500 = 2.49 → up | 3 |
Labor – Sheathing (unit hr) | {Item > Area} / 1000 * 3.5 | 1.245 × 3.5 = 4.3575 | 4.36 |
The area formulas work out in square feet, but a Qty is a count, so the answer goes into the part's unit as a plain number without a warning.
2. Drywall on a wall (unit-aware) — works
Linear item Int Wall, Linear = 142' 6", Height = 9'. ROUNDUP({Item > Linear} * {Item > Height} / 32, 0) 142.5 ft × 9 ft = 1,282.5 sf; ÷ 32 = 40.08 → 41 sheets (one side).
3. Waste from your own property — works
On the item, add Waste % (Percentage, 10). A Percentage is a fraction in formulas (10% = 0.10). {Area} * (1 + {Waste %}) with Area 1,245 sf → 1,245 × 1.10 = 1,369.5 sf. Waste and rounding order is yours: ROUNDUP({Qty} * (1 + {Item > Waste %}), 0) (waste, then round) and ROUNDUP({Qty}, 0) * (1 + {Item > Waste %}) give different answers; write the one your company uses. Rounding happens where you put it in the formula, and nowhere else. Coming the same formula with Waste % linked to a list's 25% row (1,556.25 sf).
4. Stud count (feet ÷ inches) — works
On the item, add O.C. (Number, unit in, 16). Part Studs: ROUNDUP({Item > Linear} / {Item > O.C.}, 0) + 1
- 100' wall: 16" is 1.333'; 100 ÷ 1.333 = 75 spaces (the units cancel to a plain count) → 75 + 1 = 76 studs, shown
76.00at the default 2 decimal places. - 12' wall: 144" ÷ 16" = 9 → 10 studs.
- O.C.
24on the 100' wall → 51.
5. Ignore units (familiar conversions) — works
- With units on, DimSum already converts the inches, so the
* 12counts them twice: 900. - Tick Ignore units and every reference is taken as its plain number: 100 × 12 ÷ 16 = 75. (The preview line keeps showing 900 until you apply; it always works with units on.)
Use one or the other, not both.
6. Roof area with the pitch factor Coming
Plan Area = 1,000 sf, Pitch = 6/12. {Plan Area} * PITCHFACTOR({Pitch}) → 1,000 × 1.118 = 1,118 sf; squares {Sloped Area} / 100 → 11.18; bundles at 3 per square ROUNDUP({Sloped Area} / 100 * 3, 0) → 33.54 → 34. Needs PITCHFACTOR and the Pitched Area tool's properties (Pitched Area).
7. Beam label with rounding Coming
Beam: Plies 2, Size 1 3/4" x 11 7/8", Material LVL, Member Length 15' 1". Label ({Plies}) {Size} {Material} – ROUNDTO({Member Length}, {Label Rounding}) with Label Rounding = Nearest 2 ft → "(2) 1 3/4" x 11 7/8" LVL – 16'". Text templates are built; it still needs ROUNDTO and Label Rounding Coming.
8. ROUNDTO vs. STOCKLENGTH Coming
| Length | ROUNDTO(x, "Nearest 2 ft") | ROUNDTO(x, "Up to next 2 ft (even)") | STOCKLENGTH(x, "Dimensional") |
|---|---|---|---|
| 7' 3" | 8' | 8' | 8' (shortest stock) |
| 11' 4" | 12' | 12' | 12' |
| 12' 9" | 12' | 14' | 14' |
| 13' 2" | 14' | 14' | 14' |
"Nearest" can round down, fine for a label, not for ordering.
9. List match inside a formula Coming
A part does this with an Advanced Part instead: filters Call Size equals {Item > Stud Size} and Stock Length at least {Item > Height}, sorted smallest first, on a Material Library table (the studs). The MATCH form below is for a formula.
Dimensional Lumber row 210-12 | 2x10x12 | SPF | #2 | Nom. Width 2 | Nom. Depth 10 | Length 12' | $17.40. A 2-ply 2x10 beam at 11' 4": MATCH("Dimensional Lumber", "Nom. Width", {Item > Nominal Width}, "Nom. Depth", {Item > Nominal Depth}, "Length", ROUNDTO({Item > Member Length}, "Up to next 2 ft (even)")) → row 2x10x12; {Match > Item #} → 210-12. The list's Cost column is a column you made (no money is built in).
10. A choice by a checkbox — works with your own properties
Add Treated (Checkbox) to the item, and PT Cost and SPF Cost (Number) to the part. Give the part's Cost Each the formula IF({Item > Treated}, {PT Cost}, {SPF Cost}) → the PT cost when Treated is ticked. (The LOOKUP version of this reads a Dynamic List — designed, not built, no build named.)
11. Roof edge flashing — works with your own properties
Add Eave LF = 60' and Rake LF = 40' (Number, unit ft) to the item. Drip edge in 10' pieces with 5% waste: ROUNDUP(({Item > Eave LF} + {Item > Rake LF}) * 1.05 / 10, 0) → 100 × 1.05 = 105; ÷ 10 = 10.5 → 11 pieces. (The Pitched Area tool will measure Eave and Rake for you — designed, not built.)
12. Concrete slab volume (unit conversion) — works
Area 1,200 sf, Thickness 4" (the item's own Thickness, in inches):
{Item > Area} * {Item > Thickness}→ sf × in = 400 cf.- Put it in a property whose unit is
cy(a Number whose unit iscy, or a part whose unit iscy) and it is converted: 14.81 CY. - With 5% waste on a part whose unit is
cy:{Item > Area} * {Item > Thickness} * 1.05→ 420 cf = 15.56. - To order whole yards, round in yards: add Concrete CY (Number, unit
cy) to the item with{Item > Area} * {Item > Thickness} * 1.05→ 15.56, then give the part QtyROUNDUP({Item > Concrete CY}, 0)→ 16. Rounding inside the part's own formula doesn't do it:ROUNDUP({Item > Area} * {Item > Thickness} * 1.05, 0)rounds 420 cf to 420 and still stores 15.56 CY. Rounding to the half yard inside the formula needsCONVERT.
13. Low-voltage cable run (any trade) — works
Linear item Cat6 Run, Linear = 180'.
| Part | Qty formula | Result |
|---|---|---|
Cat6 Cable, 10% slack (unit ft) | {Item > Linear} * 1.10 | 198 (ft) |
| └ Spools (1,000 ft) | ROUNDUP({Parent > Qty} / 1000, 0) | 1 |
| J-Hooks, one per 4' | ROUNDUP({Item > Linear} / 4, 0) | 45 |
Labor – Pull cable (unit hr) | {Item > Linear} / 100 * 0.75 | 1.35 |
14. Text, Division and SubDivision — works
- SubDivision:
{Level > Name} & " Walls"→ "Main Level Walls" on the Main Level, "Second Level Walls" on the Second Level. - Joining a number into text drops its unit and uses a plain number:
{Name} & ": " & {Linear}→ "Ext Wall 2x6: 142.5". "2x" & {Stud Depth} & " @ " & {O.C.} & """ o.c."→2x6 @ 16" o.c.- the Joist Tool's label is this kind of formula,
=CONCAT("J", {Mark #}, ": ", {Joist Material > Description}, " @ ", {O.C. Spacing}, """ O.C.")→J1: 2x10x16 SPF #2 @ 16" O.C.: the numbers join with no trailing zeros, and"""writes the inch mark (Joist & Rafter tools). - the same thing as a text template —
2x{Stud Depth} @ {O.C.}" o.c.in Text… writes theCONCATfor you. Numbers join without their units:{Name}: {Linear}reads "Ext Wall 2x6: 142.5", not 142' 6". Coming{Level > Label Prefix}(Level has only Name and Elevation).
15. Enable a part conditionally — works
Add Glued (Checkbox) to the item. On Subfloor Glue, set Enabled to the formula {Item > Glued}. Untick Glued and the glue part turns off and drops out of every total. Or keep it on and write the Qty as IF({Item > Glued}, ROUNDUP({Parent > Qty} / 4, 0), 0).
16. Children and parents — works
- Hours in minutes on one part are converted. Every child must have the property: one without it makes the SUM show ERROR (There is no property called "Labor Hours" on Glue).
{Children > Qty} + 1is ERROR: "{Children > Qty} can only be used inside SUM, COUNT, AVG, MIN or MAX".
17. Stud length by wall height (IFS) — works
On the item, add Stud Length (Number, unit in, Show as feet and inches ticked) with: IFS({Item > Height} <= 8.09375, 92.625, {Item > Height} <= 9.09375, 104.625, {Item > Height} <= 10.09375, 116.625) Height is in feet, so the bare numbers are feet (8.09375' = 8' 1 1/8"), and the results go into inches.
- A 9' 1 1/8" wall → 104 5/8" (shown
8'-8 5/8"). - A 12' great-room wall → no test is true → ERROR in red, "IFS: no condition was TRUE", so you notice and pick the right stud. (Add
TRUE, 0at the end if you want a default instead.) Condition… writes this for you from three If rows, and reads it back as the same three rows.
18. Project-wide totals Coming
SUMIF({Tools > Qty}, {Tools > Name} = "Ext Wall") — needs SUMIF (no build named) and {Tools > …}.
19. Assembly constraint Coming
IF({Layer > Joists > Depth} > 11.875, 1.125, 0.75) → a 14" TJI gets 1 1/8" subfloor.
20. What errors and warnings look like — works
| Formula | Problem | What you see |
|---|---|---|
{Linear} + {Area} | ft + sf | The value still shows, with an amber mark: "Mismatched units: ft + sf; the result stays in ft". Tick Ignore units to silence it |
ROUND(1, 2, 3) | Wrong number of arguments | ERROR: "ROUND takes 1 or 2 arguments (got 3)" |
A = {B}, B = {A} | Cycle | ERROR on both: "Circular: A → B → A" |
{Hieght} | Typo | ERROR: "There is no property called "Hieght" on Ext Wall 2x6" |
{Area} / {Point Count} with Point Count = 0 | Divide by zero | ERROR: "Divide by zero" |
{Parent > Qty} on an item | Nothing above it | ERROR: "Ext Wall 2x6 has nothing above it for {Parent} to reach" |
Qty * 2 | Missing braces | ERROR: "Unknown name 'Qty': references go in braces, like {Qty}" |
ROUNDTO({Item > Linear}, "Nearest 2 ft") | Not built yet | ERROR: "ROUNDTO is not available yet. It arrives with the Behind the scenes tables ." |
{Settings > Crew Rate} | Scope not built yet | ERROR: "{Settings > …} is not available yet. Coming, with User & Company." |
{Material > Cost} on a part with no material | Nothing linked | Blank, with an amber mark: "no material linked", and a warning in Needs attention — not ERROR |
{Table > Framing > Stud Spacing} on an item never set from Framing | No row to read | ERROR: "Nothing here is set from Framing — use Set from a table… first" |
{Item > Linear} * 2 on an unscaled sheet | No scale | —, not ERROR |
21. Price Each: the maths is yours — works
Every part has Cost Each, Markup %, Price Each, Tax Rate and Taxable, all blank. DimSum never works one out from another. With Cost Each 4 and Markup % 25:
- Price Each stays blank until you give it a formula.
- fx on Price Each:
{Cost Each} * (1 + {Markup %})→ 4 × 1.25 = 5.00. - Your own Tax (Number):
IF({Taxable}, {Qty} * {Price Each} * {Tax Rate}, 0)→ 0 until you tick Taxable and fill Tax Rate.
22. An Input Condition — works
{IS TRIM}or{IS TRIM} = TRUE— shows the row while the IS TRIM checkbox is ticked.AND({IS TRIM}, {Item > Height} > 8)— only on trim, and only on walls over 8'.- A condition in ERROR shows the row, with the error on hover: a broken condition never hides a value.
Tips & shortcuts
- Use the Property Picker instead of typing paths; it always inserts the right reference.
- Select part of a formula and click ROUNDUP or IF to wrap it.
- Give spacings and heights a unit when you add them; then
{Item > Linear Total} / {Item > O.C.}just works. - Either let DimSum convert, or tick Ignore units.
- Prefer
{Item > …}over{Parent > Parent > …}in deep part trees. - Use
ROUNDUP(…, 0)for anything you buy whole: sheets, boxes, tubes. It is the only way to round a Qty. - End an
IFSwithout aTRUEdefault when an unexpected case should shout (example 17). - Keep rates on the job (
{Job > Labor Rate}), so one change reprices every part.
Rules, limits & edge cases
- Formulas only read; they never change other values.
- Division by zero shows ERROR.
- Unit mismatches are warnings only; they never block a value.
- Text that looks like a number (
"12.5") works as that number; other text in arithmetic is ERROR. Text is never equal to a number ("1" = 1is FALSE). {Children > X}only works directly insideSUM,COUNT,AVG,MINorMAX, and every child part that is on must have property X.- A
/in a part name is just a character:>is the only separator, so{Parent > Subfloor 3/4" T&G > Qty}reads correctly with no escaping. - The preview line always works with units on; the Ignore units box takes effect when you apply.
- Name, Description, Colour, Opacity, Height, Thickness and Line Width on an item, and a part's Name, take a formula — and the answer reaches the canvas, the Project Tree, the Takeoff list and the Estimating tab, not just the Properties panel. A value the drawing cannot use (a blank, a negative height, a colour that is not a colour) leaves the drawing alone. Clearing one of these leaves the answer the formula last read, the same rule as Unlink. A tool's own Type (Linear, Area, Count) is set when it is made and takes none. A part's Qty Unit takes no formula at all, and its row has no fx — "Qty Unit is a unit, not a formula".
- Formulas can't reach outside the job.
- A name may not contain
{,}or>(nor[,],\,/or:), on a property or a part; DimSum says which character when it refuses. Nothing in DimSum Defaults uses them. - — the Properties Toggle was dropped. A property marked Hidden in its Settings… is still stored and still calculated.