Report Syntax

Report Syntax

Relatics allows users to create reports to share their project data. This allows others to view your data in cases where they do not have access to Relatics or would rather view the data in a Word/PDF file. Additionally, generating a report can provide a snapshot of current project data.

The reports feature is accessed by clicking Reports in the workspace menu.

Relatics syntax

A report originates from a template. The template determines which data will be printed in the report and how it will be visualized. This article will focus on the syntax used to make report templates. Before we dive into examples of syntax constructions, please note that a template has to be built in Microsoft Word. In the Word document, you can use Relatics syntax and Word functionalities simultaneously. This gives you access to styling in Word and, in turn, creative control over the presentation of your data.

Changes in the Relatics software that affect the output of a report result in an increment of the syntax version. This article describes the syntax used in the latest version of the syntax version.

RelaticsContent

[#RelaticsContent#]
Hello world!
[Action]
Id: {@Id}
Name: {Name}
A string
[.]
[#.RelaticsContent#]
------------------------------
The following won't be parsed.
[Action]
Id:{@Id}
[.]

Hello World!

Id: ACT-1
Name: Cleaning the windows
A string

Id: ACT-2
Name: Sweeping the floor
A string

--------------------------------------------
The following won't be parsed.
[Action]
Id: {@Id}
[.]

While processing a template, Relatics can distinguish between parsable syntax and other text to be printed in the report. You must point Relatics to where it parses syntax. To indicate which parts of the template are to be parsed surround the syntax by the following brackets: [#RelaticsContent#].

To illustrate, consider the example above. From the closing brackets [#.RelaticsContent#] onwards we did not specify Relatics to parse syntax. Consequently, the text after the brackets will be printed as plain text in the output.

Note:

  • A template may contain multiple instances of [#RelaticsContent#] brackets.

Iterator

[#RelaticsContent#]
[Action]
Id: {@Id}
Name: {Name}
[.]
[#.RelaticsContent#]

Id: ACT-1
Name: Cleaning the windows

Id: ACT-2
Name: Sweeping the floor

Id: ACT-3
Name: Painting the wall

In the example above, [Action] is an iterator. By using an iterator in a template, Relatics is instructed to ‘iterate’ through all elements of the specified type element (e.g. Action). In other words, Relatics will go through every element in the type element Action. Between the iterator tags, Relatics is instructed to parse syntax for every iteration of the specified type (e.g. Action). In the example, this means that for every Action, the ID and Name are printed.

Notes:

  • An iterator can be recognized by brackets and the name of a type within the brackets. For example, [Action].
  • An iterator must always be closed by brackets with a dot. For example, [.].

Inserter

[#RelaticsContent#]
[Action] {@Id} - {Name}
[.]
[#.RelaticsContent#]

ACT-1 - Cleaning the windows 

ACT-2 - Sweeping the floor 

ACT-3 - Painting the wall

In the template examples given earlier, you may have noticed model references between curly braces (e.g. {Name}). These so-called inserters are used to define which Relatics properties will be printed in the report output.

Notes:

  • What is between curly braces must equate to one value per iteration.
  • A single iterator can have multiple inserters.

Next to properties, system attributes can be used for inserters. System attributes are not defined by a power user but, instead, are predefined by Relatics. Inserters with system attributes can be recognized by the @ symbol. Notice how, in the example given earlier, the inserter {@Id} was responsible for printing the IDs of the Iterator Action.

System attribute Description
{@Id}
This system attribute prints the value in the corresponding element ID column (e.g. ACT-1).
{@DisplayName} This system attribute prints the value of the display name of an element part of a collection relation.
{@User} This system attribute prints the first and last name of the user generating the report.
{@Workspace} This system attribute prints the workspace name from which the report is generated.
{@ProjectDateTime} This system attribute prints the date and time of the project as of generating the report.

Images

[#RelaticsContent#]
[Verifications] Description: {Description}
{Image | PICTURE}
[.]
[#.RelaticsContent#]

To include images in a report, an addition to the inserter of an attachment property is required. By default, the inserter returns the name of the file. Using the following syntax {propertyName| PICTURE}, the image is inserted in the report instead of the name.

Note:

  • This feature is only available for type properties of the datatype ‘Attachment’.
  • Place the picture syntax in a table to fixate the maximum picture size in your report. In the table, set the column setting to ‘Fixed Column Width’.
  • File types without a thumbnail get a substitute image with the text ‘No image available’.

Nesting

[#RelaticsContent#]
[Person]{Name}: [is responsible for: Action]{Name}
[.Action][.Person]
[#.RelaticsContent#]

John: Cleaning the windows

Jane: Sweeping the floor

Mary: Painting the wall

An iterator is an instruction for Relatics to reach specific type elements. It gives navigational instructions to the reports engine, similar to how you click on an element Relatics table to navigate its relations and properties. It is possible to print the Actions by a responsible Person in the report output. We can achieve this in the reports syntax by nesting our iterators like in the example above. With the iterator [Person], an iteration is started through all elements of the Person type element. Nested in is another iterator [is responsible for: Action], which for each person, iterates across all their actions. The Actions are printed because of the {Name} inserter.

You may have noticed that the iterators in the template above have been closed by other means than [.]. In practice, there is no difference between mentioning the iterator in the closing brackets and closing the iterator with a dot. For simplicity’s sake, it is good practice to end iterators with [.], but if your template contains multiple nested iterators, it can improve readability if you close an iterator using the type element’s full name. Thus, glancing at the template, you can see where each iterator’s end tag is located.

Alternatively, you can instruct Relatics to follow a nested path within a single inserter. Similarly to a URL, you separate the model references within the inserter with a forward slash. The following example will show how to reach the same output without using two iterators.

[#RelaticsContent#]
[Person]{Name}: {is responsible for: Action/Name}
[.]
[#.RelaticsContent#]

John: Cleaning the windows

Jane: Sweeping the floor

Mary: Painting the wall

Note:

  • Within the inserter braces, multiple paths can be used, but it must lead to a single value per iteration.

Separator

[#RelaticsContent#]
[Action]{Name} and [.]
[#.RelaticsContent#]

Cleaning the windows and Sweeping the floor and Painting the wall and

Consider the template script above. Notice that the ‘and’ at the end of the output is undesirable if you want to deliver a concise report. After all, we just want to summarize every Action and stop once the last Action has been printed. The extra ‘and’ is printed because in the script we instruct Relatics to print the Name property for every Action, but also to print ‘and’ for every Action.

To prevent situations like this, an optional operator [|] can be used, called the separator. The separator can exclusively be used within an iterator. The fragment of the iterator behind the Separator is repeated for every iteration except the last one.

[#RelaticsContent#]
[Action]{Name} [|]and [.]
[#.RelaticsContent#]

Cleaning the windows and Sweeping the floor and Painting the wall

Table

Relatics reports support printing Relatics data in a table format. While building your template, you can use the table functionalities of Microsoft Word.

The example above shows a table template printing the element ID and Name of an Action, as well as, the Person responsible for that Action.

  • Rows numbered show table header rows, they will be printed using the same styling.
  • Rows numbered 2 will not be printed, they are rows used to tell Relatics where the iterator is opened and closed.
  • The cells between the rows with the iterator tags (3) declare inserters and print text for each iteration. In this example, row 3 will, for every iteration of Action, print a table row containing Action ID, Name and the Person responsible.

Table with cell merging

Now imagine an Action that has multiple responsible People. To account for this, you can opt to use cell merging similar to how a Relatics table shows multiple relations.


Notice that there is a slight difference between the location of the second iterator in this example as opposed to the example given in the ‘Table’ paragraph. The iterator [has responsible:Person] has been moved to another row in order to print single cells, as opposed to full rows. Let’s see how the table looks without using cell merging.

 

Note:

  • Configuring tables with Report syntax allows you to freely order around properties and relations in columns, there is no predefined order in which to put them.

Filter

It is possible to apply filters to the iterators in your template. Filters are specified within iterator brackets and it is possible to apply multiple filters on a single iterator. The following example will elaborate on the syntax used to apply a filter in a Report:
[#RelaticsContent#]
[Action | FILTER({Status} = "New")] Action: {Name} - Status: {Status}
[.]
[#.RelaticsContent#]

Action: Sweeping the floor - Status: New

To apply a filter to an iterator, start by putting a pipe symbol after the type element name. Then type FILTER and write your filter operation between parentheses. In this case, Status is a list property of the Action type element and we used it to filter for Relatics elements with a Status property of ‘New’.

It is only possible to filter by certain property types:

Property type Template Printed in output
List
[#RelaticsContent#]
[Action | FILTER({Status} IN ("New", "Busy"))]{Name}: {Status}
[.]
[#.RelaticsContent#]
Cleaning the windows: Busy

Sweeping the floor: New
Date [#RelaticsContent#]
[Action | FILTER({Deadline} > "1950-01-01") FILTER({Deadline} < "2050-01-01")]{Name}, Deadline: {Deadline}
[.]
[#.RelaticsContent#]
Cleaning the windows, Deadline: 2002-01-02

Sweeping the floor, Deadline: 2002-01-03

Painting the wall, Deadline: 2002-01-01
Number [#RelaticsContent#]
[Action | FILTER({has responsible: Person/Age} NOTEMPTY) FILTER({has responsible: Person/Age} >= 18)]{Name} - Age: {has responsible: Person/Age}
[.]
[#.RelaticsContent#]
Cleaning the windows - Age: 31

Sweeping the floor - Age: 33

Painting the wall - Age: 32

Filters can also be applied to iterators containing Relations without specified properties. However, you are only able to filter whether a relation ‘exists’ or does ‘not exist’:
[#RelaticsContent#]
[Action | FILTER([has responsible: Person] EXISTS)]{Name}
[.]
[#.RelaticsContent#]

Cleaning the windows

Sweeping the floor

Painting the wall

The script syntax for ‘not exist’ is NOTEXISTS.

Notes:

  • It is not possible to filter by specific instances.
  • It is possible to apply multiple filters within a single iterator, e.g. [Action | FILTER({has responsible: Person/Age} NOTEMPTY) FILTER({has responsible: Person/Age} >= 18)]
  • When a filter on a nested iterator should also affect the parent iterator, the filter needs to be repeated on its parent.
  • A filter’s styling (e.g., different fonts, font sizes, and colors) cannot differ from that of its iterator; differences may lead to syntax errors.
  • A filter of date and list properties will need the value between quotes, but a filter of a number property will not need the value between quotes.
  • The report can only parse dates in the format yyyy-mm-dd; dates in other formats may lead to syntax errors.
  • You are able to filter by collection relations. To illustrate, take our example above and imagine an Action can have a Person or an Organization responsible for it. You can choose whether to filter:
    1. By Person exclusively. E.g. [Action | FILTER([has responsible: Person] EXISTS)]
    2. By Organization exclusively. E.g. [Action | FILTER([has responsible: Organization] EXISTS)]
    3. By Person or Organization. E.g. [Action | FILTER([has responsible: *] EXISTS)]

Sort

Report syntax allows for the inclusion of sorting, similar to the sorting system of a column in a Relatics table. A report output with a template with no defined sorting, defaults to a sorting on the element Id of an iterator (even when {@Id} has not been printed).

Now consider:
[#RelaticsContent#]
[Action | SORT({has responsible: Person/Name})]
{has responsible: Person/Name} is in charge of {@Id} {Name}
[.]
[#.RelaticsContent#]

Jane is in charge of ACT-2 Sweeping the floor

John is in charge of ACT-1 Cleaning the windows

Mary is in charge of ACT-3 Painting the wall

To apply sorting to an iterator, start by putting a pipe symbol after the type element name. Then type SORT and write your sorting operation between parentheses. In the example, sorting is applied to a relation of the Action iterator. By disclosing a path to the Name property of a responsible Person, we have instructed the iterator to sort alphabetically by their names.

Optionally, we can tell Relatics to sort an iterator in reverse order by using DESC or force regular order by using ASC:
[#RelaticsContent#]
[Action | SORT({has responsible: Person/Name} DESC)]
{has responsible: Person/Name} is in charge of {@Id} {Name}
[.]
[#.RelaticsContent#]

Mary is in charge of ACT-3 Painting the wall

John is in charge of ACT-1 Cleaning the windows

Jane is in charge of ACT-2 Sweeping the floor

Notes:

  • It is possible to apply multiple sorts within a single iterator.
  • Lists are not sorted alphabetically, but rather on the order of list items in a property.
  • Making the styling of a sort different to that of its iterator is not supported and may lead to syntax errors.
  • Type elements that have positioning enabled will be sorted according to their positioning in the workspace.

Skip if not exists & skip if empty

There are scenarios when it is impractical to print certain elements or properties, for instance, when they do not contain data. These cases can be solved by adding a skip if not exists prefix and postfix around an iterator or a skip if empty prefix and postfix around an inserter. Let’s look at a case where you are reporting on Actions assigned to a responsible Person:
[#RelaticsContent#]
[Person]{Name}
[?]Actions: [is responsible for: Action]
- {Name}[.]
Thank you for your service, {Name}![.?]
[.]
[#.RelaticsContent#]

Jane

Actions:

- Sweeping the floor

Thank you for your service, Jane!

John

Actions:

- Cleaning the windows

Thank you for your service, John!

Mary

Actions:

- Painting the wall

Thank you for your service, Mary!

Tom

Tom has no actions, so we decide not to print Actions and a thank you message. We used the prefix [?] to instruct Relatics where to start skipping text if there is no existing iterator. Then, we used the postfix [.?] to instruct where it stops skipping text. With this skip if not exists construction, we avoided printing unwanted text for Tom.

Note:

  • You can also use the skip constructions in tables.
  • The skip if empty prefix and postfix can be placed around an inserter to skip text around property values which are empty. Instead of brackets, you use accolades like so: [#RelaticsContent#]
    [Person]{?}{Name}
    {.?}Actions: [is responsible for: Action]
    - {Name}[.]
    [.]
    [#.RelaticsContent#]

Parameters

For some reports, it is practical to allow users to add their own text whenever they generate the report. To facilitate this need, you can use parameters in the report template. Take a look at this earlier example to which we added a parameter:

[#RelaticsContent#]
{$Schedule}
[Person]{Name} is responsible for {is responsible for: Action/Name}
[.]
[#.RelaticsContent#]

When generating this report, a user will see a dialog with a single text input field titled: ‘Schedule’. In this example, a user has typed: ‘Schedule for week 32‘. The output document would look as follows:

Schedule for week 32
John is responsible for Cleaning the windows
Jane is responsible for Sweeping the floor
Mary is responsible for Painting the wall

Another perk of using parameters in the report template is letting users influence a filter for an iterator. Let’s say someone is interested in all actions that must be completed before a specific date. Using a parameter in the filter criteria allows them to pick a different date for every report they generate. Consider the following template:

[#RelaticsContent#]
These actions need to be completed before {$Deadline}.
[Action | FILTER({Deadline} < {$Deadline})]{Name} - {Deadline}
[.]
[#.RelaticsContent#]

When generating this report, a user will see a dialog with a single date input field titled: ‘Deadline’. In this example, a user has selected ‘2002-01-03’. The output document would look as follows:

These actions need to be completed before 2002-01-03.
Cleaning the windows - 2002-01-02
Painting the wall - 2002-01-01

Note:

  • Similar constructions can be made for iterators filtered by their number or list properties.

Widgets

Some reports may benefit from a more informative visual format of your project data. Therefore, you may want to include charts in your report, similar to the widgets in your project dashboard. To generate charts in reports, you can use the charts function in Word to create Population divider and Population in time widgets. The following Word chart types are supported:

  • Population divider: doughnut and stacked column.
  • Population in time: line with markers and stacked column.

Population divider

PopulationDivider("People responsible for actions")
TypeElement([Action])
DivideBy([has responsible: Person])

let’s add a population in time widget to a report. If a similar widget is already available on a Relatics dashboard, it is convenient to copy the report script. If not, you can create it from scratch. In either case, it is required to put some report syntax in Word. In the following example, we will create a chart that shows the number of actions a person is responsible for.

  1. Insert a chart of the correct type in Word.
  2. Specify the widget type in the chart’s title using the following syntax:PopulationDivider("People responsible for actions")
  3. Open the chart’s spreadsheet by choosing edit data in the chart’s context menu.
  4. Specify a population using an iterator with a type element name. The syntax for the population should be placed in cell B1, formulated like:TypeElement([Action])
  5. Specify how the population should be divided by putting the following syntax in cell A2. The division of the population can be based on a property or a relation, defined by an inserter or iterator between brackets. This is an example of division by a relation:DivideBy([has responsible: Person])

Notes:

  • Filters can be added by adding to the syntax in cell B1. These filters are based on a list type property and are defined as follows:TypeElement([Action]) Filter({Status = "New")
  • By default, archived elements are not counted towards the total population. If you want to include archived elements in the population, you can add this to the syntax in cell B1, formulated like so:TypeElement([Action]) IncludeArchived()
  • A report script copied from a dashboard will contain the syntax for a chart title, a specified population, and how the population should be divided. However, this syntax will still need to be put in the proper location in Word.

Population in time

PopulationInTime("Actions by week")
Population("Actions") TypeElement([Action]) Count()
TimeAxis("Year", "Weekly")

To generate a population in time widget in a report, it is convenient to copy the report script from a Relatics dashboard. However, it is also possible to create it from scratch in Word. In either case, it is required to put some report syntax in Word. Let’s create a report that shows a line chart of the total number of actions for the past year.

  1. Insert a chart of the ‘line with markers’ type in Word.
  2. Specify the widget type in the chart’s title using the following syntax:PopulationInTime("Actions by week").
  3. Open the chart’s spreadsheet by choosing edit data in the chart’s context menu.
  4. In a single line of syntax, name the population, specify a population using an iterator, and tell Relatics whether to count the total or take the sum or average of a property value. Put the syntax in cell B1 in the spreadsheet:Population("Actions") TypeElement([Action]) Count()
  5. Optionally, you can create syntax for a second population by repeating step four and inputting it in cell C1.
  6. Define the length and number of periods on the x-axis. In this case, we tell Relatics to divide the time axis by weeks in a year with the following syntax, which we put in cell A2:TimeAxis("Year", "Weekly")

Notes:

  • Filters can be added to the population by adding to the syntax in cell B1. These filters are based on a list property and are defined as follows:Population("Actions") TypeElement([Action]) Filter({Status = "New") Count()
  • The length of periods on the x-axis can be set to Week, Month, QuarterYear, HalfYear, or Year. The interval can be set to Daily, Weekly, or Monthly.
  • If you want to use the sum or average of a number property as a population, you can specify that property with an inserter. For example:Population("Actions") TypeElement([Action]) Sum({Hours until completion})

Request a demo

Fill in our form and one of our colleagues will contact you as soon as possible to schedule a demo.

Please enable JavaScript in your browser to complete this form.
Please enable JavaScript in your browser to complete this form.

Download the whitepaper

Please enable JavaScript in your browser to complete this form.
Addresss

Get in touch

Fill in our form and one of the Relatics members will contact you as soon as possible. Do you prefer contact by phone? Please call us at +31 180 413 047.
Please enable JavaScript in your browser to complete this form.