Write expressions in QGIS
A QGIS expression works out a value from the fields of a feature. For example, "street" || ', ' || "suburb" shows Smith St, Brunswick. You write an expression in the Expression Builder of QGIS.
In the QGIS User Guide: Expressions and List of functions.
Where Groundwork reads an expression
Groundwork reads an expression in these places of your project:
- A label, and the condition of a label rule. See Style a layer in QGIS.
- The condition of a style rule, in a Rule-based style.
- A Default value, and the Expression under Constraints. See Set up the edit form in QGIS.
- Control Visibility by Expression on a group of the form, and the Data defined override beside Editable.
- The Filter expression of a Value Relation.
- The expression beside a box under Permissions, on the QField tab that the QFieldSync plugin adds to Layer Properties. See Lock some edits.
Groundwork works out each expression with the rules of QGIS. For example, a comparison with a field that has no value is neither true nor false.
Functions and operators
In this table, “Everywhere” means all the places in the list above.
| Function or operator | What Groundwork does | Where it works |
|---|---|---|
"field", 'text', numbers, TRUE, FALSE and NULL | The field’s value, or the value as written | Everywhere |
|| and concat | Join text. concat leaves out a field with no value, and || gives no value | Everywhere |
+, -, * and / | Calculate with numbers, and + also joins two pieces of text. A field with no value, or other text that is not a number, gives no value. + and - with make_interval move a date. Groundwork does not calculate with other dates | Everywhere |
//, % and ^ | Divide and round down to a whole number, take the remainder of a division, or raise to a power. A division by zero gives no value. ^ comes before * and /, and after a minus sign, so -2 ^ 2 is 4, as in QGIS | Everywhere |
=, <>, !=, <, <=, > and >= | Compare two values. A comparison with a field that has no value is neither true nor false. Groundwork compares dates as text | Everywhere |
AND, OR and NOT | Join or reverse conditions, as in QGIS | Everywhere |
IS, LIKE, ILIKE, IN and BETWEEN | Test a value, as in QGIS. IS NOT, NOT LIKE, NOT ILIKE, NOT IN and NOT BETWEEN work too | Everywhere |
~ | Test text against a regular expression, such as "asset_id" ~ '^A\\d{3}$'. As in QGIS, \\w and \\d match only A to Z, 0 to 9 and _ here, not a letter such as é | Everywhere |
CASE WHEN … THEN … ELSE … END and if | Choose a value by a condition | Everywhere |
coalesce and nullif | The first value that is not empty. nullif gives no value where two values are the same, such as nullif("status", '(none)') | Everywhere |
upper, lower, title and trim | Change the case of text, or remove the spaces at its ends | Everywhere |
length, strpos, left, right, substr and replace | Count, find, cut or change text. replace takes the text, what to find and what to put in its place, not a map | Everywhere |
lpad and rpad | Pad text on the left or the right to a width | Everywhere |
wordwrap | Break text into lines of a length, at its spaces or at a character you name, such as wordwrap("species", 12) | Everywhere |
regexp_match, regexp_replace and regexp_substr | Find, replace or take out the text that a regular expression matches. In the replacement, \\1 is the first group. The pattern must be written into the expression. Groundwork reads the everyday forms of a pattern, such as [A-Z], \\d+, (…) and |. It does not read a rarer form, such as (?s), [[:alpha:]], a named group or \\1 | Everywhere |
round and format_number | Round a number, or write it with separators. Without a language, format_number uses Australian English | Everywhere |
max and min | The largest or smallest of several numbers. A field with no value is skipped | Everywhere |
abs, floor and ceil | A number without its sign, or rounded down or up to a whole number | Everywhere |
to_int, to_real and to_string | Turn text into a whole number or a decimal number, or a number into text | Everywhere |
format_date | Write a date in a QGIS pattern, such as 'd MMM yyyy'. A pattern with t, the name of a time zone, is not read | Everywhere |
year, month, day, week, day_of_week, hour, minute and second | A part of a date, read as format_date reads one. week is the ISO week of the year, and day_of_week counts from 0 for Sunday | Everywhere |
now() and $now | The date and time on the device | Inside format_date, year and the other parts of a date. As a whole default value, also in to_date or to_datetime, it fills in today’s date |
make_interval | A length of time, such as make_interval(days:=14), added to a date or taken from one, as in "inspected" + make_interval(days:="days"). A month counts as 30 days and a year as 365.25, as in QGIS | Everywhere, after + or - and a date |
char | A character by its number, such as char(10) for a new line | Everywhere |
$area, $length and $perimeter | Measure the shape, in the units that the project sets. A record with no shape has no value | Everywhere except the filter of a Value Relation |
current_value | The value of a field in the form, such as current_value('family') | The filter of a Value Relation, Control Visibility by Expression and the override on Editable. In a label or a style rule it has no value. A default value or a constraint that uses it is not read |
maximum and minimum | The largest or smallest value of an expression among the layer’s records. With group_by or filter, it is not read | Default values only |
overlay_within and overlay_intersects, read by array_first, array_get or an index such as [0] | The value of an expression on a feature of another layer that a new point lies within or meets, such as array_first(overlay_within('Properties', "prop_propnum")). Groundwork asks that layer’s source for the features around the point, as QGIS does. A line or a polygon is not looked up, and only polygons are matched | Default values only |
aggregate with the filter intersects($geometry, geometry(@parent)), which takes geometry and @parent | A count, min, max or concatenate of the features of another layer under a new point, in the form that QField’s guide gives. Any other kind of aggregate, filter or order_by is not read | Default values only |
uuid() | A new ID | A whole default value only |
Any other function, such as regexp_matches, a variable other than @parent in aggregate, or a named value such as places:=2 outside make_interval | Groundwork does not read the expression. What happens then depends on where it is | Nowhere |
When Groundwork cannot read an expression
Groundwork does not show a warning when it cannot read an expression. What it does depends on where the expression is:
| Where the expression is | What Groundwork does |
|---|---|
| A label | Draws no label for that layer or rule |
| The condition of a label rule | Uses that rule’s label on every feature |
| The condition of a style rule | Draws that rule’s symbol on every feature |
| A Default value | Leaves the field as it is |
| The Expression under Constraints | Skips that rule, so the save goes ahead |
| Control Visibility by Expression | Shows the fields of the group |
| The Data defined override beside Editable | Locks the field only if its Editable box is unticked |
| The Filter expression of a Value Relation | Offers every row of the table |
| The expression beside a QFieldSync Permissions box | Locks that edit |
Open the map in Groundwork to check each expression before you share the map.