Expressions
Expressions compute what a report shows: visible, filter, variables, sort keys, group keys and chart values are
expressions, and text is a text template with expressions in braces. They are a small, sandboxed
language: no code from .NET runs, so templates from people you do not fully trust are safe. Every expression is
type-checked in the scope it runs in when the template is compiled, before any data is read.
visible: =Total > 0 # a property that takes an expression starts with =filter: Status == 'open' # where only an expression fits, the = is optionalvalue: "{Customer}: {Sum(Total):C2}" # a text templateText templates
Section titled “Text templates”Text properties (value, title, alt, link…) are text templates: text with expressions in braces.
{Sum(Total):C2}formats the value with a .NET format after the colon, in the report’s culture.{{and}}are literal braces.- A colon only starts a format outside parentheses and strings, so a condition in a template is written in
parentheses:
{(Paid ? 'Paid' : 'Due')}. - A template that is exactly one expression with no format, such as
"{Logo}", gives the value itself rather than text. That is how images, barcodes and attachments take bytes from your data.
boolean, integer, decimal, double, string, date, dateTime, time and bytes. Any value can be null.
42is an integer,4.2a decimal and4.2e0a double. Strings are in'single'or"double"quotes, with\n,\t,\\,\'and\"escapes.- Integers widen to decimals or doubles as needed. Decimals and doubles never mix:
Price * Ratewith a decimal price and a double rate is an error that suggestsToDecimal()orToDouble(), so money never passes silently through binary floating point. - Dividing two integers gives a decimal:
7 / 2is 3.5. - An integer that overflows is an error, not a wrap-around.
Operators
Section titled “Operators”From the lowest precedence to the highest:
| Operators | |
|---|---|
a ? b : c |
Condition |
a ?? b |
a, or b when a is null |
|| |
Or |
&& |
And |
== != |
Equal, not equal |
< <= > >= |
Comparison |
+ - |
Add, subtract; + with text on either side joins them, formatting the other side in the report’s culture |
* / % |
Multiply, divide, remainder |
! - + |
Not, negate |
Writing =, <>, & or | gives an error that says what to write instead.
Nulls follow SQL: arithmetic with null is null; comparisons with null are false, except == null; a condition that
is null counts as false; and aggregates skip nulls. ?? and Coalesce put a value in its place. In a
text template, null shows as nothing.
A name is looked up, in order, as a field of the current table row, a field of the body row, a
variable, a group (its current key), a
parameter, then PageNumber and TotalPages.
- Names are case-sensitive; a near miss gets a “did you mean” suggestion.
Parent.Xreads the enclosing row’s fieldXfrom inside a table or chart, where a field of the same name would hide it:filter: =InvoiceId == Parent.Id.- An expression that uses
PageNumberorTotalPagesis evaluated during layout, once the pages are known.
Aggregates
Section titled “Aggregates”Sum, Count, Avg, Min, Max, First and Last summarize the rows of a scope: Sum(Total),
Avg(Quantity * Price), Count().
- An optional last argument names the scope:
'report', a group’s name, or a dataset’s name:Sum(Quantity * UnitPrice, 'lines'). - Without it, a group’s header or footer covers its group, the detail its innermost group, a table’s cells and footer the table’s rows, and everything else the whole report.
- With no rows,
SumandCountare 0 and the others are null.Avgof integers is a decimal. - Aggregates cannot be nested or use
PageNumber, and are not allowed in filters, sort keys, group keys or parameter defaults. A group’s header can show its group’s total: it is computed before the header is laid out.
Functions
Section titled “Functions”Function names are not case-sensitive.
Upper(text)
The text in upper case, by the report’s culture. Null when an argument is null.
Lower(text)
The text in lower case, by the report’s culture. Null when an argument is null.
Trim(text)
The text without white space at either end. Null when an argument is null.
Len(text)
The length of the text, in characters. Null when an argument is null.
Left(text, count)
The first count characters of the text, or all of it if it is shorter. Null when an argument is null.
Right(text, count)
The last count characters of the text, or all of it if it is shorter. Null when an argument is null.
Substring
Section titled “Substring”Substring(text, start, length?)
The part of the text from start (counting from 0), length characters long or to the end. Positions past the end are clamped. Null when an argument is null.
Contains
Section titled “Contains”Contains(text, value)
Whether the text contains value (case-sensitive). Null when an argument is null.
StartsWith
Section titled “StartsWith”StartsWith(text, value)
Whether the text starts with value (case-sensitive). Null when an argument is null.
EndsWith
Section titled “EndsWith”EndsWith(text, value)
Whether the text ends with value (case-sensitive). Null when an argument is null.
Replace
Section titled “Replace”Replace(text, find, replacement)
The text with every find replaced by replacement (case-sensitive). An empty find changes nothing. Null when an argument is null.
PadLeft
Section titled “PadLeft”PadLeft(text, width, char?)
The text padded on the left to width characters with char, a space by default: PadLeft(Code, 6, '0'). Null when an argument is null.
PadRight
Section titled “PadRight”PadRight(text, width, char?)
The text padded on the right to width characters with char, a space by default. Null when an argument is null.
IsEmpty
Section titled “IsEmpty”IsEmpty(text)
Whether the text is null or empty.
Numbers
Section titled “Numbers”Abs(number)
The absolute value, of the same type. Null when an argument is null.
Round(number, digits?)
The number rounded to digits decimal places (0 by default, at most 15), halves away from zero: Round(2.5) is 3. Of the same type. Null when an argument is null.
Floor(number)
The largest whole number not greater than the number, of the same type. Null when an argument is null.
Ceiling
Section titled “Ceiling”Ceiling(number)
The smallest whole number not less than the number, of the same type. Null when an argument is null.
Least(value, value, ...)
The smallest of the values, which may be numbers, text, dates or times. Nulls are skipped.
Greatest
Section titled “Greatest”Greatest(value, value, ...)
The largest of the values, which may be numbers, text, dates or times. Nulls are skipped.
Conversion
Section titled “Conversion”ToDecimal
Section titled “ToDecimal”ToDecimal(value)
A number, or text such as '1234.5' (invariant culture), as a decimal. Null when an argument is null.
ToDouble
Section titled “ToDouble”ToDouble(value)
A number, or text such as '1.5e3' (invariant culture), as a double. Null when an argument is null.
ToInteger
Section titled “ToInteger”ToInteger(value)
A number, or text such as '42', as an integer. Decimals and doubles are truncated towards zero. Null when an argument is null.
Format
Section titled “Format”Format(value, format?)
The value as text, with a .NET format and the report’s culture: Format(Total, 'C') is what {Total:C} shows in a text template.
Today()
Today’s date, from the clock the report is filled with, so a report can be reproduced. Null when an argument is null.
Now()
The date and time, from the clock the report is filled with. Null when an argument is null.
Date(year, month, day)
A date. Null when an argument is null.
Year(date)
The year of a date or date and time. Null when an argument is null.
Month(date)
The month (1 to 12) of a date or date and time. Null when an argument is null.
Day(date)
The day of the month of a date or date and time. Null when an argument is null.
AddDays
Section titled “AddDays”AddDays(date, days)
The date moved by a number of days (negative to go back), of the same type. Null when an argument is null.
AddMonths
Section titled “AddMonths”AddMonths(date, months)
The date moved by a number of months, of the same type. The day is kept, or becomes the month’s last: 31 January plus one month is the end of February. Null when an argument is null.
AddYears
Section titled “AddYears”AddYears(date, years)
The date moved by a number of years, of the same type. Null when an argument is null.
DaysBetween
Section titled “DaysBetween”DaysBetween(from, to)
The number of days from from to to, negative when to is earlier. Null when an argument is null.
Coalesce
Section titled “Coalesce”Coalesce(value, value, ...)
The first value that is not null.
IsNull
Section titled “IsNull”IsNull(value)
Whether the value is null.
Formats
Section titled “Formats”The text after the colon in {value:format}, and the second argument of Format, is a .NET format
string, applied in the report’s culture. For example, in en-US:
| Template | Shows |
|---|---|
{1234.5:C} |
$1,234.50 |
{1234.5:C0} |
$1,235 |
{1234.5:N0} |
1,235 |
{0.256:P0} |
26% |
{0.256:P1} |
25.6% |
{3.14159:F1} |
3.1 |
{42:D5} |
00042 |
{3.5:000.00} |
003.50 |
{Date(2026, 9, 24):d} |
9/24/2026 |
{Date(2026, 9, 24):D} |
Thursday, September 24, 2026 |
{Date(2026, 9, 24):yyyy-MM-dd} |
2026-09-24 |
{Date(2026, 9, 24):MMM yyyy} |
Sep 2026 |
In de-DE the first one is 1.234,50 € and {0.256:P0} is 26 %. Give the number of decimals (N2, C2, F1):
without it, the default comes from the operating system’s culture data and can differ between systems. See .NET’s
numeric and
date and time format
strings for all of them.
Errors
Section titled “Errors”A mistake in an expression is found when the template is compiled, with where it is: the property’s path and the
column. A problem that only the data can cause, such as a division by zero or a value of the wrong type in a field,
shows #Error where the value would be and is reported with its row, or fails the report if you prefer
(FillOptions.Errors).