Calculations
Introduction
What are calculations?
Calculations in Fortes Change Cloud allow you to enrich Custom Fields with logic. They are written in XML and can perform operations such as adding fields, comparing values, aggregating data from child objects, and more. Calculations are the backbone of advanced configuration in FCC, enabling automated data processing across portfolios, projects, and other objects.
Who uses calculations?
Calculations are created and maintained by System Administrators and consultants who configure the FCC data model. They are typically used to automate field values, enforce business rules, and create derived metrics across the portfolio and project hierarchy.
Three ways to populate a Custom Field
Custom fields can be populated in three ways:
- Manual entry: The user fills in the value by hand.
- Conditional logic: A value is only written to the field if a specific condition is met.
- Calculation: The value is computed automatically using XML-based calculation blocks.
Objects reference table
Every object in FCC has a reference number (foldertype). These numbers are used in calculations to target specific object types. Below is the complete reference table.
| Foldertype | Internal object name | English | Dutch |
|---|---|---|---|
| 3 | Person | Resource | Resource |
| 4 | KnowledgeRepository | Knowledge Repository | Kennisbibliotheek |
| 16 | Skill | Skill | Skill |
| 76 | Currency | Currency | Valuta |
| 81 | Timesheet | Time Sheet | Weekstaat |
| 83 | CostEntry | Cost / Hour Entry | Boekingsregel (kosten/uren) |
| 84 | TimesheetRow | Time Sheet Row | Weekstaatregel |
| 100 | Entry | Entry | Boekingsregel |
| 301 | DocumentBase | Document | Document |
| 302 | DocumentHistory | Document | Document |
| 500 | OrganizationalUnit | Organisational Unit | Organisatie-eenheid |
| 701 | Portfolio | Portfolio | Portfolio |
| 703 | PortfolioModel | Portfolio Model | Portfolio model |
| 711 | PortfolioDashboard | Custom Dashboard | Eigen Overzicht |
| 720 | Benefit | Benefit | Benefit |
| 730 | Scenario | Scenario | Scenario |
| 4900 | ProjectBase | Project Base | Project Base |
| 4901 | Idea | Idea | Idee |
| 4910 | ProgramProject | Programme | Programma |
| 4911 | ProgramProjectModel | Programme Model | Programmamodel |
| 5000 | P2Project | Project | Project |
| 5002 | P2ProjectTemplate | Project Model | Projectmodel |
| 5003 | ProjectReport | Portfolio Item | Portfolio-item |
| 5004 | ProjectReportsHistory | Version | Versie |
| 5005 | ProjectReportModel | Report Model | Rapportagemodel |
| 5006 | SavedProjectReport | Saved Portfolio Item | Bewaard portfolio-item |
| 5010 | ProjectPublication | Project publication | Project publication |
| 5031 | ProjectRole | Project Role | Project Rol |
| 5100 | P2Program | Folder | Map |
| 5110 | P2ProgramProject | MSP Programme | MSP Programma |
| 5111 | P2ProgramTemplate | MSP Programme Model | MSP-programmamodel |
| 5301 | P2Stage | Stage | Fase |
| 5302 | P2Product | Product | Product |
| 5303 | P2Workpackage | Workpackage | Werkpakket |
| 5499 | NonProjectActSets | NPA set container | NPA set container |
| 5500 | NonProject | Non-project Activity Set | Niet-project activiteitenset |
| 5501 | NonProjectCategory | Category | Categorie |
| 5502 | NonProjectActivity | Non-project Activity | Niet-project activiteit |
| 5510 | TimeRegistrationGroup | Time Entry Group | Tijdregistratiegroep |
| 5519 | TimeRegistrationConfigurations | Time Entry Configurations | Tijdregistratieconfiguraties |
| 5520 | TimeRegistrationConfiguration | Time Entry Configuration | Tijdregistratieconfiguratie |
| 5602 | PlanItem | Plan Item | Planning-item |
| 6001 | P2Issue | Issue | Issue |
| 6011 | P2Risk | Risk | Risico |
| 6021 | P2Quality | Quality review | Kwaliteitsbeoordeling |
| 6031 | P2Change | Change | Wijziging |
| 6041 | P2Action | Action | Actie |
| 6051 | P2Lessonlearned | Lesson learned | Leerpunt |
| 6061 | Order | Order | Order |
| 8017 | ProjectResource | Project Resource | Project Resource |
Calculation syntax
Single calculation
Calculations are written in XML. The most common form is a single calculation:
<calculation>
<!-- This is a comment and has no effect on the XML code -->
<block></block>
</calculation>
Key rules:
- Every calculation must start with
<calculation>and end with</calculation>. These tags are case-sensitive. - Inside a calculation you define blocks that perform a specific operation (e.g.
<cmp/>,<add/>). - Use XML comments (
<!-- ... -->) to document what the calculation does. This is considered best practice.
Multiple calculations
When you need multiple calculation blocks (for example, to execute different logic depending on conditions), wrap them in a <calculations> (plural) element:
<calculations>
<!-- Execute when condition A is met -->
<calculation>
<condition></condition>
<block></block>
</calculation>
<!-- Execute when condition B is met -->
<calculation>
<condition></condition>
<block></block>
</calculation>
</calculations>
XML writing tips
- Use indentation. Indentation is not required for the XML to function, but it makes calculations much easier to read and maintain.
- Use comments. Document your choices and explain what each block does. This ensures the calculation is understandable even when someone else revisits it later.
Calculation blocks
Calculation blocks are the building blocks inside a <calculation>. Each block performs a specific operation. You can use one or multiple blocks in a single calculation.
Add
The <add> block calculates the sum of the specified fields.
| Attribute | Value | Description |
|---|---|---|
minus | true / false | Set on a <field> to negate its value |
Example: Add two fields:
<calculation>
<add>
<field>Custom1</field>
<field>Custom2</field>
</add>
</calculation>
Example: Subtract (add with minus):
<calculation>
<add>
<field>Custom1</field>
<field minus='true'>Custom2</field>
</add>
</calculation>
Result: Custom1 + (-Custom2) = Custom1 - Custom2
Compare
The <cmp> block compares one or more fields/values. Returns True, False, or a custom result.
| Attribute | Values | Description |
|---|---|---|
value | Any value | Fixed value used in the comparison |
condition | equals, smaller, smallerequals, greater, greaterequals, not, in, not in, empty, not empty | The comparison operator |
result | Any value | Custom value to return when the comparison is true |
Example: Equals check:
<calculation>
<cmp condition='equals' value='test'>
<field>Custom1</field>
</cmp>
</calculation>
Returns True if Custom1 equals "test".
Example: Not equals with custom result:
<calculation>
<cmp condition='not' value='test' result='my value'>
<field>Custom1</field>
</cmp>
</calculation>
Returns "my value" if Custom1 is not equal to "test".
Example: In list:
<calculation>
<cmp condition='in' value='value1,value2,value3'>
<field>Custom1</field>
</cmp>
</calculation>
Returns True if Custom1 matches any of the listed values.
Example: Greater than using nested value:
<calculation>
<cmp condition='greater'>
<field>Custom1</field>
<value>10</value>
</cmp>
</calculation>
Concatenate
The <concat> block joins multiple fields or values together into a single string.
| Attribute | Value | Description |
|---|---|---|
separator | Any value | Placed between the concatenated values. Default: no separator |
The <field> element inside <concat> supports additional attributes:
| Attribute | Description |
|---|---|
offset | Number of characters to skip from the beginning of the field value |
length | Number of characters to keep from the beginning of the field value |
minlength | Minimum length the field value must have |
Example: Concatenate with separator:
<calculation>
<concat separator=" " subfolders="true" relation="planning" foldertype="5602">
<field>Owner</field>
</concat>
</calculation>
If there are 3 planning children, returns: Owner1 Owner2 Owner3
Example: Concatenate multiple fields and values:
<calculation>
<concat separator="+">
<field>EntryType</field>
<field>P2Project</field>
<value>RowApproval</value>
</concat>
</calculation>
Returns e.g.: Planned+12345+RowApproval
Cut
The <cut> block splits a field value based on a delimiter and returns specific parts by index.
| Attribute | Value | Description |
|---|---|---|
delimiter | Any value | The character to split on (default: space) |
indexes | Comma-separated indices | Which parts to return (0-based) |
Example: Select by index (space-separated):
<calculation>
<cut>
<field indexes='0,2'>Custom2</field>
</cut>
</calculation>
If Custom2 = "One Two Three Four", returns: OneThree
Example: Select by index with delimiter:
<calculation>
<cut>
<field indexes='0' delimiter='-'>Custom1</field>
</cut>
</calculation>
If Custom1 = "One-Two-Three-Four", returns: One
Date
The <date> block calculates dates from custom periods.
| Element | Description |
|---|---|
<field> | The date field to use as input |
<startof> | Returns the start of a period (e.g. month, year) |
<endof> | Returns the end of a period |
<offset> | Adds or subtracts time intervals (weeks, months, quarters, years) |
Example: Last day of next month:
<calculation>
<date>
<field>Portfolio veld 1</field>
<offset>
<scale>months</scale>
<intervals>1</intervals>
</offset>
<endof>
<scale>month</scale>
</endof>
</date>
</calculation>
Date format
The <dateproperty> block formats a date field into a specific string representation.
| Attribute | Value | Description |
|---|---|---|
format | Format string | The date format pattern to use |
Supported format tokens:
| Token | Description | Example |
|---|---|---|
G | Era | AD |
y / yyyy | Year | 1996; 96 |
M / MM | Month in year | July; Jul; 07 |
w | Week in year | 27 |
W | Week in month | 2 |
D | Day in year | 189 |
d | Day in month | 10 |
E | Day of week (text) | Tuesday |
a | AM/PM marker | PM |
H | Hour (0-23) | 0 |
h | Hour (1-12) | 12 |
m | Minute | 30 |
s | Second | 55 |
S | Millisecond | 978 |
z | Timezone | PST; GMT-08:00 |
Example: Week number:
<calculation>
<dateProperty format="WW">
<field>Enddate</field>
</dateProperty>
</calculation>
For end date 2010-01-08, returns: 01
Example: Year with label:
<calculation>
<dateProperty format="'Year: 'yyyy">
<field>Enddate</field>
</dateProperty>
</calculation>
Returns: Year: 2010
Date calculation
The <datecalculation> block performs calculations on date fields.
Example: Current date:
<calculation>
<datecalculation>
<var>%currentdate%</var>
</datecalculation>
</calculation>
Example: First day of the year:
<calculation>
<datecalculation>
<field>Custom1</field>
<startof>
<scale>year</scale>
</startof>
</datecalculation>
</calculation>
Example: Last day of the month:
<calculation>
<datecalculation>
<field>Custom1</field>
<endof>
<scale>month</scale>
</endof>
</datecalculation>
</calculation>
Divide
The <div> block divides one field by another.
| Attribute | Value | Description |
|---|---|---|
minus | true / false | Set on a <field> to negate its value |
Example: Divide by a fixed value:
<calculation>
<div>
<field>Custom1</field>
<value>3</value>
</div>
</calculation>
Example: Divide by a negated field:
<calculation>
<div>
<field>Custom1</field>
<field minus="true">Custom2</field>
</div>
</calculation>
Folderfield
The <folderfield> block takes over the value of a field from the current object or from a referenced object.
Example: Take over field via reference:
<calculation>
<folderfield>
<field reference="ProjectReport">FolderID</field>
</folderfield>
</calculation>
Example: Take over percentage from current stage:
<calculation>
<folderfield>
<field reference="CurrentStage">PercentageCompleted</field>
</folderfield>
</calculation>
Max
The <max> block evaluates two values and returns the largest. Values must be of type double.
<calculation>
<max>
<field>20.0</field>
<field>25.0</field>
</max>
</calculation>
Returns: 25.0
Min
The <min> block evaluates two values and returns the smallest. Values must be of type double.
<calculation>
<min>
<field>20.0</field>
<field>25.0</field>
</min>
</calculation>
Returns: 20.0
Multiply
The <mul> block multiplies fields together.
| Attribute | Value | Description |
|---|---|---|
minus | true / false | Set on a <field> to negate its value |
Example:
<calculation>
<mul>
<field>Custom43</field>
<field>Custom45</field>
</mul>
</calculation>
Example: Multiply with negation:
<calculation>
<mul>
<field>Custom42</field>
<field minus="true">Custom44</field>
</mul>
</calculation>
Sum
The <sum> block sums the values of a field across all matching child objects.
If you need to add two fields on the same object, use <add> instead.
Example: Sum across all child projects:
<calculation>
<sum>
<folderFilter foldertype='5000'/>
<field>Custom1</field>
</sum>
</calculation>
Example: Sum with a name filter:
<calculation>
<sum>
<folderFilter foldertype='5000'>
<Name operator='equals' filterValues='Test Project'/>
</folderFilter>
<field>Custom1</field>
</sum>
</calculation>
True / False
The <tst> and <not> blocks evaluate a field to True or False.
Example: Test:
<calculation>
<tst>
<field>Custom1</field>
</tst>
</calculation>
Example: Not (inverse):
<calculation>
<not>
<field>Custom1</field>
</not>
</calculation>
Returns True if Custom1 is False.
Value
The <value> block returns a fixed value. Not used for calculations, but to set a constant.
<calculation>
<value>123.89</value>
</calculation>
Number of working days
The <nrworkingdays> block calculates the number of working days between two date fields.
<calculation>
<nrworkingdays>
<field>Custom1</field>
<field>Custom2</field>
</nrworkingdays>
</calculation>
Number of days between
The <nrdaysbetween> block calculates the total number of days (including weekends) between two date fields.
<calculation>
<nrdaysbetween>
<field>Startdate</field>
<field>Enddate</field>
</nrdaysbetween>
</calculation>
Count
The <count> block counts the number of matching child objects.
Example: Count portfolio items:
<calculation>
<count>
<folderFilter foldertype="5003" />
</count>
</calculation>
Example: Count with conditions:
<calculation>
<count foldertypes="301">
<condition>
<cmp value="4">
<field>DocumentType</field>
</cmp>
</condition>
</count>
</calculation>
Entry sum
The <timelinesum> block calculates the sum of all entries related to a specific object. It supports various attributes and filter options.
Main attributes
| Attribute | Values | Description |
|---|---|---|
type | Planned, Actual, Budget, Forecast, Demand, Request, Realised, etc. | Filters on the specified entry type |
hours | true / false | Include hours in the calculation |
money | true / false | Include money in the calculation |
value | true / false | Include value items in the calculation |
periodStart | Date or FIELD:FieldName | Start date of the period |
periodEnd | Date or FIELD:FieldName | End date of the period |
bookdate | Date or FIELD:FieldName | Effective single-day date |
project | %folderID% | Scope to a specific project |
timelineUnit | GUID | Correlates with a booking method and value field type |
Filter attributes
Filters can be nested inside <timelinesum> using a <filter> element:
| Filter field | Description |
|---|---|
periodStartdate | Start date of the entry |
periodEnddate | End date of the entry |
reference | Object reference of the entry (e.g. Product, Project) |
type | Entry type: Actual, Assigned, Budget, Committed, Remaining, Reserved, Capacity, Demand, Supply, Allocation, Available, Request, Planned, Estimate, EAC, ETC |
parent | The object under which the entry was added |
skill | The skill related to the booked hours |
resource | The resource related to the booked hours |
category | The financial category related to booked money |
isDraft | Final (0) or draft (1) |
program | The related folder |
programProject | The related programme |
project | The related project |
product | The related product |
stage | The related project stage |
projectReport | The related portfolio item |
resourceOU | The OU used for time registration (GroupID) or resource management (Pool) |
Booking methods
The timeline unit determines how entries are stored and retrieved.
| Booking method | Input fields | Description |
|---|---|---|
| BookdateTotal | Bookdate, Value | Booked on a single date |
| PeriodTotalWorkingDays | Startdate, Enddate, Value | Input values spread across working days |
| PeriodPerWorkingDay | Startdate, Enddate, Value | Input value is the value per working day |
Timeline units
| Timeline unit | Booking method |
|---|---|
| Hours (changed on Bookdate) | BookdateTotal |
| Money (changed on Bookdate) | BookdateTotal |
| Hours and Money (changed on Bookdate) | BookdateTotal |
| FTE (Hours per Working Day / 8) | PeriodPerWorkingDay |
| Days per Working Week (Hours per Working Day x 5) | PeriodPerWorkingDay |
| Hours per Working Day | PeriodPerWorkingDay |
| Hours (changes spread over a period) | PeriodTotalWorkingDays |
| Person Days (changes spread over a period) | PeriodTotalWorkingDays |
| Money (changes spread over working days) | PeriodTotalWorkingDays |
Example: Planned hours with a specific timeline unit:
<calculation>
<timelinesum type="Planned" timelineUnit="1281FD30-D2BD-4BD5-8529-7487F9813BA2"/>
</calculation>
Example: Actual money with date range and category filter:
<calculation>
<timelinesum type="Actual" money="true" project="%folderID%"
periodStart="2010-01-01" periodEnd="FIELD:ReportProvideStatusPer">
<filter>
<Category operator="in" filterValues="208989,208990,243797" />
</filter>
</timelinesum>
</calculation>
Calculation options
Calculations on the same object are automatically recalculated when needed. Calculations on the parent object are also automatically triggered.
However, when a calculation depends on a different object (e.g., a change in a project should trigger recalculation on the linked portfolio item), you need to configure a calculation option on the custom field.
Calculation options are not required in most cases. Only configure them when cross-object dependencies exist.
Using relations
By default, the direct parent's calculations are triggered via the "normal relation" mechanism. When you need to use a different relation (e.g. the planning structure), specify it in the calculation option.
Example: Sum across plan items (using planning relation):
<calculation>
<sum>
<folderFilter foldertype='5602'>
<field>Custom1</field>
</sum>
</calculation>
Calculation option: relation='planning'
This tells the calculation engine to trigger recalculation using the "planning" relation.
Using reference fields
When a calculation reads from a referenced object, configure the calculation option so the reference triggers recalculation.
Example: Copy field from linked project of a portfolio item:
<calculation>
<folderField reference='OperationalProject'>
<field>Custom1</field>
</folderField>
</calculation>
Calculation option: 1 (or specify the reference as needed, e.g. 1,reference=P2Project)
Calculation conditions
What are conditions?
Conditions allow you to execute a calculation only when a specific requirement is met. Use the <condition> block inside a <calculation>. The calculation only runs if the condition evaluates to true.
<calculation>
<!-- Calculation only executes if the condition is met -->
<condition/>
<block/>
</calculation>
Conditions can be defined in custom fields under the Advanced button.
Using break
To prevent subsequent calculations from running when a condition is already matched, add break='true' to the calculation:
<calculations>
<calculation break='true'>
<condition>
<cmp condition='empty'>
<field>Owner</field>
</cmp>
</condition>
</calculation>
<calculation>
<cmp condition='empty'>
<field>Parent</field>
</cmp>
</calculation>
<calculation>
...
</calculation>
</calculations>
When break='true' is set and the first condition is met, all subsequent calculations are skipped. Without the break, the engine continues evaluating every calculation block.
Condition types: AND and OR
By default, multiple <conditions> blocks are evaluated as AND. All conditions must be true:
<calculation>
<conditions>
...
</conditions>
<conditions>
...
</conditions>
</calculation>
To use OR logic (only one condition needs to be true), set type='or':
<calculation>
<conditions type='or'>
...
</conditions>
<conditions>
...
</conditions>
</calculation>
Using depends
The <depends> block specifies which fields should trigger recalculation when their value changes:
<calculation>
<depends>
<field>Custom121</field>
</depends>
<folderfield>
<field>ModificationDate</field>
</folderfield>
</calculation>
This calculation recalculates whenever Custom121 changes, and writes the modification date to the target field.
Configuring field editability and visibility
Conditions can be combined with <editCheck> and <displayCheck> to control who can edit or see a field.
Edit check
Restricts editing of a field based on a condition. In this example, only administrators can edit the field:
<calculation>
<fieldConditions>
<editCheck>
<condition>
<adminCheck/>
</condition>
</editCheck>
</fieldConditions>
</calculation>
Display check
Hides a field entirely for users who don't meet the condition. In this example, only administrators can see the field:
<calculation>
<fieldConditions>
<displayCheck>
<condition>
<admincheck/>
</condition>
</displayCheck>
</fieldConditions>
</calculation>
Example: Display check with multiple conditions:
<fieldConditions>
<displayCheck>
<conditions type="or">
<condition>
<cmp value="XXX" condition="in">
<var>CustomXX</var>
</cmp>
</condition>
<condition>
<pagefoldertype condition="in">21,23,5000,5041,5100,6021,6020</pagefoldertype>
</condition>
</conditions>
</displayCheck>
</fieldConditions>
The <pagefoldertype> filter controls on which object types the field is visible:
5000= Project5100= Folder6021= Quality review- etc.
Best practices
- Always use comments in your XML to explain the purpose of each calculation block.
- Use indentation consistently to keep calculations readable.
- Use
break='true'when using multiple conditional calculations to avoid unnecessary processing. - Test calculations on a single object before applying them broadly.
- Document calculation options: note the relation or reference configuration alongside the XML.
- Keep calculations simple: split complex logic into multiple custom fields rather than creating one massive calculation.
FAQ
Where do I create calculations? In the Configuration section of FCC. Navigate to the object type (e.g. Project), open or create a Custom Field, and enter the calculation XML in the Calculation field under Advanced.
Are calculations case-sensitive?
Yes. The XML tags (<calculation>, </calculation>, <field>, etc.) are case-sensitive and must be written exactly as documented.
When are calculations triggered? Calculations on the same object are triggered automatically when a field changes. For cross-object triggers, you need to configure a calculation option.
What happens if I divide by zero? The calculation returns an empty or zero value. It does not produce an error.
Can I nest calculation blocks?
Yes. You can nest blocks like <mul> inside <div>, or <add> inside <div>, to create complex expressions such as weighted averages or percentages.
What is the difference between <add> and <sum>?
<add> adds fields on the same object. <sum> aggregates a field across child objects (using a <folderFilter>).