*This functionality is available in Bommer v1.9 and later.*

Bommer allows you to define formulas inside text, number, and decimal properties, which can represent computed values or text. Bommer formulas are made up of a series of values (which can be Fusion parameters and/or Bommer property references) and operators to accomplish calculations such as arithmetic, unit conversion, and number formatting.

This guide is a reference for formulas and calculated fields, which includes what a formula looks like, how they are evaluated, and what operators are supported. For more information on how to how to enter formulas into Bommer (via the "Edit bill of materials…” command or “Edit part info...” command), please see the Using the Edit bill of materials table guide or Using the Edit part properties form guide; for more information about exporting bills of materials with formulas (via the "Export..." command), please see the Considerations when exporting formulas guide).

# Structure of a formula

A formula is a collection of *terms *(a term is one part of a formula, such as **1** or **+**), beginning with an equal (**=**) sign; the = tells Bommer to evaluate the field value as a formula. This is similar to how one would enter formulas into a spreadsheet cell. Also similar to spreadsheet formulas, Bommer formulas follow a pattern: *operand* operator *operand* operator *operand* etc… For example:

`= 1 + 1`

= Mass/Volume

= I & like & Bommer

These are valid formulas, to compute arithmetic, compute density from a component's mass and volume, or construct a text string that says **I like Bommer**.

# Evaluation

Formulas are evaluated left to right, and each operator will “operate” on the current value of the formula (on the left) and the value on the right to produce the next operand value. E.g.

`= 1 + 1 * 4`

In this case, Bommer will evaluate **1+1** first, produce **2**, and then evaluate **2 * 4** to produce **8**. Bommer * does not* follow the standard mathematical order of operations, it simply moves left to right. This means that when constructing formulas, you can assume that the left of an operator will be fully evaluated before the operator is applied, which can be handy for reasoning through complex unit conversions.

## Parentheses and sub-expressions

It is possible to control the order of operations through the use of parentheses. Parentheses create subexpressions that are evaluated first to compute a value that is then used in the formula. For example, if we add parentheses to our previous formula:

`= 1 + (1 * 4)`

Bommer will read 1, and then +, and then recognize that it needs to evaluate the value inside the parentheses before performing the addition. This will produce a value of 5 (e.g. 1 + 4).

# Operands

An operand is a term that represents a value that will be used in a calculation; the **1** and **2** in **1 + 2 **are operands. In Bommer formulas, operands can be:

**Literal values**e.g. strings, integers, decimal numbers, or true/false (boolean values)**User and design parameters (that exist in the design that owns the line item)**, referenced by parameter name. This is important for designs with referenced components; the design/document that is referenced will have its own set of parameters, and Bommer will look for parameters in a line item’s document vs the top-level document.**Bommer properties**, referenced by short name (e.g. Longest Dimension) or by full name (with category, e.g. Physical.Longest Dimension)

Bommer will automatically try and find matching parameter or property names for each term. For example:

`= Dim * 5`

will try to find a parameter or property called Dim from which to pull the value, or will emit a literal term if a match is not found. If Bommer finds both a parameter and a property with the exact same name, it will pick the parameter. To use the property instead, add the property category into the formula, e.g (assuming Dim is in the General category).

`= General.Dim * 5`

## Quoting operands

If a property or parameter name contains characters that could be interpreted as part of the formula, it may be necessary to surround that term in double-quotes, e.g. "...". For example, if you had a property named Qty * 5, or if the operand has characters Bommer interprets as a separate term, such as the unit m^2, you will need to wrap these terms in quotes in order to tell Bommer to read and evaluate the full property name or unit as one term.

To illustrate, using the Qty * 5 property name example:

`= Qty * 5`

will produce the literal terms Qty, *, and 5, which is not right.

This, however:

`= "Qty * 5"`

will create a reference to the property Qty * 5, because Bommer knows to read until the closing quote before attempting to find a reference.

Alternatively, if you wanted to output the name of a parameter or property without referencing its value, you can use single-quotes, e.g.:

`= 'Qty * 5'`

This will output the text string **Qty * 5** without referencing the value contained in that property.

## Units and data types

Operands in formulas will preserve the units attached to the parameters, or some Bommer properties (e.g. mass properties, bounding box properties, etc), and in many cases will perform automatic unit conversions as the terms of the formula are evaluated. This is designed to be similar to how parameters in Fusion work, e.g. linear units will combine to form other units, like area. As an example, **1 m * 1 m** will evaluate to **1 m^2** and further operations will keep or adjust these units.

For values that do not have units, you can assign units in the formula using the unit decorating operator (described below), which lets you tell Bommer that a literal value should have a specific unit. E.g.,

` =10:m * 50`

will compute a value of **50 m**. This can be useful when combining units or when applying values entered into your BOM that may not have units associated with them. It is also possible to print the units as part of your formula

In addition to units, values in formulas have an associated data type, e.g. integer, decimal, text, or true/false value. In general, you do not need to worry about the data type (Bommer will convert as needed) except to remember that certain operators may require operands of a certain type. For example, the following will be an error:

= "Metal" + "Bars"

but Bommer will correctly evaluate and produce **30**:

= 5 * "6"

# If-then-else Conditionals

Bommer supports the use of if-then-else conditional statements inside formulas, in the form of:

```
if (<condition>) then <value or expression> else <value or expression>
```

These expressions let you use one value or another based on the result of some conditional test, such as if a field is equal to a certain value, if two fields are equal, or if a property value is greater than some constant.

## Condition

The condition part of the conditional statement must be a Bommer formula or expression, wrapped in parentheses, that evaluates to true or false. As an example, consider a situation where you have two different cost calculations: one is used if the part is “made”, and the other is used if the part is “bought”. Your if statement might start with `if (Make/Buy == "Make")`

. Other examples include:

`if (Quantity > 5) ...`

`if (Process == "Saw" or (Process == "Mill")) ...`

Because the condition can be a full Bommer formula, it can be as complex as you need; you can even nest a full conditional statement in there (though we do not recommend it)!

## Then / Else

The `then`

and `else`

parts of the conditional statement define the values to use or expressions to compute if the conditional test is true or false. Here is the completed example from above:

`if (Make/Buy == "Make") then MakeCost else BuyCost`

This formula will use the value stored in the MakeCost property if Make/Buy is set to Make; otherwise it will use BuyCost. These terms can be simple values or references (which do not require parentheses), or can be full subexpressions. They can even be nested conditionals, which allows for more complex behavior, like this:

```
= if ("Food" == Fruit) then "FruitBasketList" else if ("Food" == Vegetable) then "VeggieList" else "This food does not exist"
```

💡 If you are defining a conditional test using a Multiple Choice property, consider using a nested `else if`

conditional like the one above to provide a default value if the Multiple Choice property is empty. Otherwise, you may be stuck with a lot of “Veggies”.

# Operators and effects

An operator (like in mathematics) is a symbol or character that tells Bommer how to compute a value. Bommer supports the following operators:

**Arithmetic operators +, -, *, and /**

These can operate on numbers and result in a number (integer or decimal).

**Equality operators** **== (equals), != (not equals)**

which can operate on any type of data, and result in a true/false value.

**Inequality operators**** <, >, <= (less than or equal to), >= (greater than or equal to)**

which can operate on numbers and result in a true/false value.

**Boolean operators **`and`

, `or`

, `not`

`and`

, `or`

, `not`

which can operate on true/false values or subexpressions and return a true/false value. Ex.

`Quantity == 1 and (Make/Buy == "Make")`

`Quantity > 5 or (Vendor == "ZeusTech")`

`not (Quantity == 0)`

Note that Bommer requires parentheses around the second and subsequent subexpressions when using `and`

, and `or`

. `not`

requires that the expression to be negated is wrapped in parentheses.

**String concatenation operator &**

which will join two strings together and result in a string.

**Unit conversion operator ::**

This operator takes a Fusion unit on the right side and will convert the value at that point to the specified units, e.g. **= Mass * Quantity ::lbmass. **As mentioned above, it may be required to wrap the unit in quotes.

**Unit decorating operator :**

This operator takes an un-united number on the left, and a Fusion unit on the right, and will assign the unit to the value. As mentioned, it may be required to wrap the unit in quotes if it contains characters that could be interpreted as part of the formula.

**Number format operator |**

Which takes the following values as valid inputs:

- A format string, that can take the following form:
**0.y**which will format the number to y decimal places**x.y**which will format the number to y decimal places, and occupy the space of x total characters. As an example, 1.5 has 3 total characters. This can be used to create space on the left side of the number.**x**which will format a number as an integer with space for x total characters.**0x**which will format the number to x total characters, but will add leading zeros if needed. For example**123 | 05**will add 0 leading zeros to pad it to 5 characters.**0x.y**which will format the number to x total characters, and y decimal places, and add leading zeros as needed.

**The round keyword**,- Which will round to the nearest integer

**The floor keyword**- Which will return the largest integer less than the value

**The ceil keyword**- Which will return the smallest integer greater than the value

**The rem keyword**- Which will return the fractional part of a decimal number (e.g. 1.505 will become 0.505)

**The print unit operator ~**

Which will output the units of the formula, and convert the formula to a string.

## Comments

0 comments

Please sign in to leave a comment.