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 template, 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.
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. |
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 1 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#] |
Cleaning the windows: Busy Sweeping the floor: New |
Date | [#RelaticsContent#] |
Cleaning the windows, Deadline: 2002-01-02 Sweeping the floor, Deadline: 2002-01-03 Painting the wall, Deadline: 2002-01-01 |
Number | [#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
Notes:
- It is not possible to filter by specific instances.
- It is possible to apply multiple filters within a single iterator.
- 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:
- By Person exclusively. E.g. [Action | FILTER([has responsible: Person] EXISTS)]
- By Organization exclusively. E.g. [Action | FILTER([has responsible: Organization] EXISTS)]
- 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.
Hide when empty
There are scenarios when it is impractical to print certain elements, for instance, when they do not contain data. These cases can be solved by adding a hide-when-empty prefix and/or postfix. 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 hiding empty values. Then, we used the postfix [.?] to instruct where it stops hiding empty values. With this hide-when-empty construction, we avoided printing unwanted text for Tom.
Note:
- You can also hide tables using the hide-when-empty construction.
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.