Skip to main content
Version: Version 22

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.

FoldertypeInternal object nameEnglishDutch
3PersonResourceResource
4KnowledgeRepositoryKnowledge RepositoryKennisbibliotheek
16SkillSkillSkill
76CurrencyCurrencyValuta
81TimesheetTime SheetWeekstaat
83CostEntryCost / Hour EntryBoekingsregel (kosten/uren)
84TimesheetRowTime Sheet RowWeekstaatregel
100EntryEntryBoekingsregel
301DocumentBaseDocumentDocument
302DocumentHistoryDocumentDocument
500OrganizationalUnitOrganisational UnitOrganisatie-eenheid
701PortfolioPortfolioPortfolio
703PortfolioModelPortfolio ModelPortfolio model
711PortfolioDashboardCustom DashboardEigen Overzicht
720BenefitBenefitBenefit
730ScenarioScenarioScenario
4900ProjectBaseProject BaseProject Base
4901IdeaIdeaIdee
4910ProgramProjectProgrammeProgramma
4911ProgramProjectModelProgramme ModelProgrammamodel
5000P2ProjectProjectProject
5002P2ProjectTemplateProject ModelProjectmodel
5003ProjectReportPortfolio ItemPortfolio-item
5004ProjectReportsHistoryVersionVersie
5005ProjectReportModelReport ModelRapportagemodel
5006SavedProjectReportSaved Portfolio ItemBewaard portfolio-item
5010ProjectPublicationProject publicationProject publication
5031ProjectRoleProject RoleProject Rol
5100P2ProgramFolderMap
5110P2ProgramProjectMSP ProgrammeMSP Programma
5111P2ProgramTemplateMSP Programme ModelMSP-programmamodel
5301P2StageStageFase
5302P2ProductProductProduct
5303P2WorkpackageWorkpackageWerkpakket
5499NonProjectActSetsNPA set containerNPA set container
5500NonProjectNon-project Activity SetNiet-project activiteitenset
5501NonProjectCategoryCategoryCategorie
5502NonProjectActivityNon-project ActivityNiet-project activiteit
5510TimeRegistrationGroupTime Entry GroupTijdregistratiegroep
5519TimeRegistrationConfigurationsTime Entry ConfigurationsTijdregistratieconfiguraties
5520TimeRegistrationConfigurationTime Entry ConfigurationTijdregistratieconfiguratie
5602PlanItemPlan ItemPlanning-item
6001P2IssueIssueIssue
6011P2RiskRiskRisico
6021P2QualityQuality reviewKwaliteitsbeoordeling
6031P2ChangeChangeWijziging
6041P2ActionActionActie
6051P2LessonlearnedLesson learnedLeerpunt
6061OrderOrderOrder
8017ProjectResourceProject ResourceProject 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.

AttributeValueDescription
minustrue / falseSet 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.

AttributeValuesDescription
valueAny valueFixed value used in the comparison
conditionequals, smaller, smallerequals, greater, greaterequals, not, in, not in, empty, not emptyThe comparison operator
resultAny valueCustom 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.

AttributeValueDescription
separatorAny valuePlaced between the concatenated values. Default: no separator

The <field> element inside <concat> supports additional attributes:

AttributeDescription
offsetNumber of characters to skip from the beginning of the field value
lengthNumber of characters to keep from the beginning of the field value
minlengthMinimum 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.

AttributeValueDescription
delimiterAny valueThe character to split on (default: space)
indexesComma-separated indicesWhich 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.

ElementDescription
<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.

AttributeValueDescription
formatFormat stringThe date format pattern to use

Supported format tokens:

TokenDescriptionExample
GEraAD
y / yyyyYear1996; 96
M / MMMonth in yearJuly; Jul; 07
wWeek in year27
WWeek in month2
DDay in year189
dDay in month10
EDay of week (text)Tuesday
aAM/PM markerPM
HHour (0-23)0
hHour (1-12)12
mMinute30
sSecond55
SMillisecond978
zTimezonePST; 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.

AttributeValueDescription
minustrue / falseSet 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.

AttributeValueDescription
minustrue / falseSet 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.

tip

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​

AttributeValuesDescription
typePlanned, Actual, Budget, Forecast, Demand, Request, Realised, etc.Filters on the specified entry type
hourstrue / falseInclude hours in the calculation
moneytrue / falseInclude money in the calculation
valuetrue / falseInclude value items in the calculation
periodStartDate or FIELD:FieldNameStart date of the period
periodEndDate or FIELD:FieldNameEnd date of the period
bookdateDate or FIELD:FieldNameEffective single-day date
project%folderID%Scope to a specific project
timelineUnitGUIDCorrelates with a booking method and value field type

Filter attributes​

Filters can be nested inside <timelinesum> using a <filter> element:

Filter fieldDescription
periodStartdateStart date of the entry
periodEnddateEnd date of the entry
referenceObject reference of the entry (e.g. Product, Project)
typeEntry type: Actual, Assigned, Budget, Committed, Remaining, Reserved, Capacity, Demand, Supply, Allocation, Available, Request, Planned, Estimate, EAC, ETC
parentThe object under which the entry was added
skillThe skill related to the booked hours
resourceThe resource related to the booked hours
categoryThe financial category related to booked money
isDraftFinal (0) or draft (1)
programThe related folder
programProjectThe related programme
projectThe related project
productThe related product
stageThe related project stage
projectReportThe related portfolio item
resourceOUThe OU used for time registration (GroupID) or resource management (Pool)

Booking methods​

The timeline unit determines how entries are stored and retrieved.

Booking methodInput fieldsDescription
BookdateTotalBookdate, ValueBooked on a single date
PeriodTotalWorkingDaysStartdate, Enddate, ValueInput values spread across working days
PeriodPerWorkingDayStartdate, Enddate, ValueInput value is the value per working day

Timeline units​

Timeline unitBooking 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 DayPeriodPerWorkingDay
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.

note

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 = Project
  • 5100 = Folder
  • 6021 = 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>).