> For the complete documentation index, see [llms.txt](https://docs.agilecase.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.agilecase.com/developer-documentation/case-scripting/calculated-fields/a-simple-calculated-multiplier.md).

# A Simple Calculated Multiplier

The smallest useful calculated field — read one value, return a formatted number.

The smallest calculated field worth writing: read one field, do one piece of arithmetic, return the answer as text. Everything else a calculated field does is a variation on this.

## The scenario

A club's annual subscription is the number of members multiplied by the standard fee. The total is quoted in renewal letters, so it has to be available as a merge field, not just on screen.

| Setting          | Value                            |
| ---------------- | -------------------------------- |
| Calculated field | `6401` Annual subscription total |
| Source field     | `6402` Number of members         |
| Standard fee     | £7 per member                    |

## The script

```javascript
function calc() {
    var memberCount = Service.CustomField(6402).ValueAsText;

    if (memberCount === "") {
        return String((0).toFixed(2));
    }

    return String((parseFloat(memberCount) * 7).toFixed(2));
}
```

## Why a calculated field and not a label

A [JavaScript label](/developer-documentation/custom-form-scripting.md) could work this out too, and would update as the user typed. What it could not do is put the total in the renewal letter, because a label's output is only ever on the screen.

A calculated field recalculates wherever its value is needed — on the tab, in a document or email template, and through the [Case Data API](/developer-documentation/case-data-api.md) — which is the whole reason to choose one.

The trade is that it does not react while the user types. It is calculated when the tab is rendered, so a change to the member count shows in the total after the form is saved and reloaded.

## calc and its return value

The script must define `calc()`, and `calc()` must return something the server can turn into text. Returning nothing, or an object, produces **Calculated Field Error** in the field — and in any document carrying its merge field.

Wrapping the answer in `String(...)` is the habit that avoids this. `toFixed(2)` does the same job for money, and fixes the number of decimal places at the same time, so `56` is quoted as `56.00`.

You can define other functions alongside `calc()`. Only `calc()` is called; see [Building a Multi-Part Total](/developer-documentation/case-scripting/calculated-fields/building-a-multi-part-total.md) for a script that uses that.

## Handling an empty field

An empty field read through `ValueAsText` gives an empty string, and `parseFloat("")` gives `NaN`, which would reach the letter as the literal text `NaN`. The early return keeps that out.

{% hint style="warning" %}
`Service.CustomField(id).ValueAsNumber` handles whole numbers only: a field holding `12.5` reads as `0`, not `12`. Read `ValueAsText` and convert with `parseFloat` for anything that can carry a decimal point.

Note also that `ValueAsText` is a property here, with no brackets. In a JavaScript label the equivalent, `CustomField(id).ValueAsText()`, is a function. The two environments are not interchangeable.
{% endhint %}
