Skip to main content
Knowledge Basev14.5

Formula Fields

A formula custom field's value is automatically calculated by Celoxis based on its formula. The value is calculated every time the field is rendered. The formula expression language is sophisticated so you can perform complex data manipulations including arithmetic, string and date transformations.

Syntax

Celoxis treats anything between

and

as expressions. Formulas can be either defined as pure expressions e.g.

, or contain a mix of text and expressions as

when anything enclosed in

and

is treated as an expression and evaluated, while everything outside it is copied to the output verbatim as is. For the curious, if the formulae were attached to a project whose name was

and budget was

the output would be

and

respectively.

The dot operator

The dot operator is used to reference a property of an object. In the example

, the

refers to the project's budget if the custom field is attached to a project. The dot operator can also be used to call a function (a.k.a. method) of an object. In the example

, the

is a function call that would transform the project's name to upper case characters.

Operators

  • Arithmetic: +, - (binary), *, / and div, % and mod, - (unary)
  • String Concatenation: +=
  • Logical: and, &&, or, ||, not, !
  • Relational: ==, eq, !=, ne, <, lt, >, gt, <=, ge, >=, le. Comparisons can be made against other values or against Boolean, string, integer, or floating-point literals.
  • Empty: The empty operator is a prefix operation that can be used to determine whether a value is null or empty.
  • Conditional: A ? B : C. Evaluate B or C, depending on the result of the evaluation of A.
  • Assignment: =
  • Semicolon: ;

The precedence of operators highest to lowest, left to right is as follows:

  • [] .
  • () (used to change the precedence of operators)
  • - (unary) not ! empty
  • * / div % mod
  • + - (binary)
  • +=
  • < > <= >= lt gt le ge
  • == != eq ne
  • && and
  • || or
  • ? :
  • =
  • ;

Reserved Words

The following words are reserved for the EL and should not be used as identifiers:

andornoteq
neltgtle
getruefalsenull
instanceofemptydivmod

Basic Examples

FormulaResult
${1 > (4/2)}false
${4.0 >= 3}true
${100.0 == 100}true
${(10*10) ne 100}false
${'a' < 'b'}true
${'hip' gt 'hit'}false
${4 > 3}true
${1.2E4 + 1.4}12001.4
${3 div 4}0.75
${10 mod 4}2
${!empty me.code}False if the object's code is null or an empty string.

Utility Functions

The following set of helper functions have been provided:

formatDate(date)The formatted value of date (without the time) as per viewer's preferences.
formatDateTime(datetime)The formatted value of date and time as per viewer's preferences.
formatNumber(number)The formatted value of the number as per the viewer's locale.
formatCurrency(number)The formatted value of currency as per the currency specified in the company's preferences and number format as per the viewer's locale. E.g. $25,000
hoursToHHMM(number)Formats the hours in the form HH:MM. For example, 2.5 will result in 2:30

Writing multi-line formulas

To write the formula code on multiple line, use the = and ; operators. The return value is the last statement of the formula. For example:

${
apc = me.actualPercentComplete;
ppc = me.plannedPercentComplete;
(apc - ppc)/ppc
}

The formula return data type

While defining a formula, you have to select a Formula Data Type. This tells the system what it should expect the formula to return. Celoxis formats the return value automatically based on the data type. For example, if you indicate the return type to be a currency, then if your formula returns a number 10000, the output would be $10,000 i.e. Celoxis automatically formats the number and prefixed it with the company's currency symbol.

The me object

The me object in formula represents the object for which the formula is being evaluated. E.g. let's say that our formula field Client Advance is defined as ${me.budget * 0.1} i.e it represents 10% of the budget. If we have attached this field to both projects and tasks, then while evaluating the formula for a project, the me object would be a project while for a task it would be a task object.

Field reference

To view the list of available fields, click on the Field Reference tab on the add/edit custom field screen. Click on the plus icon to expand the list of available variables for the various entities.

Error handling

When there is an error evaluating a formula, e.g. you passed a number where a string was expected, the output would show ERR!. Move your mouse over it to get a better description of the problem.

Examples

Assume that we have a project with the following data.

LabelFieldValue
IDid1234
NamenameSetting up office space
StartstartCalendar10 January, 2011
Budgetbudget5000
Estimated CostestimatedCost4000
Actual CostactualCost3800

We'll now look at a few simple examples. We shall assume that the formula is attached to projects and the sample output is for the project described above.

FormulaOutputComments
${me.id * 10}12340id is multiplied by 10
me.id * 10me.id * 10Not enclosed in ${} and hence copied to the output verbatim.
ID:${me.id}ID:1234Text mixed with an expression
${me.name + 100}ERR!Cannot perform arithmetic on String type.
${me.abcd}ERR!me does not have a property named abcd.
${formatDate(me.startCalendar)}Jan 10, 2011Formats the start date as per the user's date format style.
${me.actualCost gt (me.budget*.9) ? 'ALERT' : 'OK'}ALERTAn example on how to write if/then/else
${formatCurrency(me.budget)}$ 5,000Assuming your currency symbol is $
${round(((me.budget - me.actualCost)*100)/me.budget)}%24%Calculates the % of budget remaining

Advanced Example: Your own schedule health indicator

Let's say that you want to have a schedule health indicator that is based on baselines i.e. the date you actually promised to the customer rather than on the current plan's finish date.

You will create a formula field, attach it to projects, set it's output data type to Text and enter the formula as:

${
pc = me.actualPercentComplete;
pFinish = me.projectedFinishCalendar;
bFinish = me.baselineFinish;
now = Date.now();
label = 'Unknown';
label = Date.before(pFinish,  bFinish) ? 'On Time' : label;
label = Date.after(pFinish, bFinish) ? 'At Risk' : label;
label = Date.after(now, bFinish) ? 'Overdue' : label;
label = pc == 100 ? 'Completed' : label;
label
}

In the Color part of the formula put the mappings as:

ResultColor
On TimeGreen
At RiskOrange
OverdueRed
CompletedBrown