Le fragment de code sur cette page nécessite les importations suivantes:

from qgis.core import (
   edit,
   QgsExpression,
   QgsExpressionContext,
   QgsFeature,
   QgsFeatureRequest,
   QgsField,
   QgsFields,
   QgsVectorLayer,
   QgsPointXY,
   QgsGeometry,
   QgsProject,
   QgsExpressionContextUtils
)

Expressions, Filtrage et Calcul de valeurs

QGIS propose quelques fonctionnalités pour faire de l’analyse syntaxique d’expressions semblable au SQL. Seulement un petit sous-ensemble des syntaxes SQL est géré. Les expressions peuvent être évaluées comme des prédicats booléens (retournant Vrai ou Faux) ou comme des fonctions (retournant une valeur scalaire). Voir Expressions dans le manuel Utilisateur pour une liste complète des fonctions disponibles.

Trois types basiques sont supportés :

  • nombre — aussi bien les nombres entiers que décimaux, par exemple 123, 3.14

  • texte — ils doivent être entre guillemets simples: 'hello world'

  • référence de colonne — lors de l’évaluation, la référence est remplacée par la valeur réelle du champ. Les noms ne sont pas échappés.

Les opérations suivantes sont disponibles:

  • opérateurs arithmétiques: +, -, *, /, ^

  • parenthèses: pour faire respecter la précédence des opérateurs: (1 + 1) * 3

  • les unaires plus et moins: -12, +5

  • fonctions mathématiques: sqrt, sin, cos, tan, asin, acos, atan

  • fonctions de conversion : to_int, to_real, to_string, to_date

  • fonctions géométriques: $area, $length

  • Fonctions de manipulation de géométries : $x, $y, $geometry, num_geometries, centroid

Et les prédicats suivants sont pris en charge:

  • comparaison: =, !=, >, >=, <, <=

  • comparaison partielle: LIKE (avec % ou _), ~ (expressions régulières)

  • prédicats logiques: AND, OR, NOT

  • Vérification de la valeur NULL: IS NULL, IS NOT NULL

Exemples de prédicats:

  • 1 + 2 = 3

  • sin(angle) > 0

  • 'Hello' LIKE 'He%'

  • (x > 10 AND y > 10) OR z = 0

Exemples d’expressions scalaires:

  • 2 ^ 10

  • sqrt(val)

  • $length + 1

Analyse syntaxique d’expressions

The following example shows how to check if a given expression can be parsed correctly:

exp = QgsExpression('1 + 1 = 2')
assert(not exp.hasParserError())

exp = QgsExpression('1 + 1 = ')
assert(exp.hasParserError())

assert(exp.parserErrorString() == '\nsyntax error, unexpected $end')

Évaluation des expressions

Expressions can be used in different contexts, for example to filter features or to compute new field values. In any case, the expression has to be evaluated. That means that its value is computed by performing the specified computational steps, which can range from simple arithmetic to aggregate expressions.

Expressions basiques

Cette expression basique est évaluée à 1, signifiant « vrai »:

exp = QgsExpression('1 + 1 = 2')
assert(exp.evaluate())

Expressions avec entités

To evaluate an expression against a feature, a QgsExpressionContext object has to be created and passed to the evaluate function in order to allow the expression to access the feature’s field values.

The following example shows how to create a feature with a field called « Column » and how to add this feature to the expression context.

fields = QgsFields()
field = QgsField('Column')
fields.append(field)
feature = QgsFeature()
feature.setFields(fields)
feature.setAttribute(0, 99)

exp = QgsExpression('"Column"')
context = QgsExpressionContext()
context.setFeature(feature)
assert(exp.evaluate(context) == 99)

The following is a more complete example of how to use expressions in the context of a vector layer, in order to compute new field values:

from qgis.PyQt.QtCore import QVariant

# create a vector layer
vl = QgsVectorLayer("Point", "Companies", "memory")
pr = vl.dataProvider()
pr.addAttributes([QgsField("Name", QVariant.String),
                  QgsField("Employees",  QVariant.Int),
                  QgsField("Revenue", QVariant.Double),
                  QgsField("Rev. per employee", QVariant.Double),
                  QgsField("Sum", QVariant.Double),
                  QgsField("Fun", QVariant.Double)])
vl.updateFields()

# add data to the first three fields
my_data = [
    {'x': 0, 'y': 0, 'name': 'ABC', 'emp': 10, 'rev': 100.1},
    {'x': 1, 'y': 1, 'name': 'DEF', 'emp': 2, 'rev': 50.5},
    {'x': 5, 'y': 5, 'name': 'GHI', 'emp': 100, 'rev': 725.9}]

for rec in my_data:
    f = QgsFeature()
    pt = QgsPointXY(rec['x'], rec['y'])
    f.setGeometry(QgsGeometry.fromPointXY(pt))
    f.setAttributes([rec['name'], rec['emp'], rec['rev']])
    pr.addFeature(f)

vl.updateExtents()
QgsProject.instance().addMapLayer(vl)

# The first expression computes the revenue per employee.
# The second one computes the sum of all revenue values in the layer.
# The final third expression doesn’t really make sense but illustrates
# the fact that we can use a wide range of expression functions, such
# as area and buffer in our expressions:
expression1 = QgsExpression('"Revenue"/"Employees"')
expression2 = QgsExpression('sum("Revenue")')
expression3 = QgsExpression('area(buffer($geometry,"Employees"))')

# QgsExpressionContextUtils.globalProjectLayerScopes() is a convenience
# function that adds the global, project, and layer scopes all at once.
# Alternatively, those scopes can also be added manually. In any case,
# it is important to always go from “most generic” to “most specific”
# scope, i.e. from global to project to layer
context = QgsExpressionContext()
context.appendScopes(QgsExpressionContextUtils.globalProjectLayerScopes(vl))

with edit(vl):
    for f in vl.getFeatures():
        context.setFeature(f)
        f['Rev. per employee'] = expression1.evaluate(context)
        f['Sum'] = expression2.evaluate(context)
        f['Fun'] = expression3.evaluate(context)
        vl.updateFeature(f)

print( f['Sum'])

Filtrer une couche à l’aide d’expressions

L’exemple suivant peut être utilisé pour filtrer une couche et ne renverra que les entités qui correspondent au prédicat.

layer = QgsVectorLayer("Point?field=Test:integer",
                           "addfeat", "memory")

layer.startEditing()

for i in range(10):
    feature = QgsFeature()
    feature.setAttributes([i])
    assert(layer.addFeature(feature))
layer.commitChanges()

expression = 'Test >= 3'
request = QgsFeatureRequest().setFilterExpression(expression)

matches = 0
for f in layer.getFeatures(request):
   matches += 1

assert(matches == 7)

Gestion des erreurs dans une expression

Les erreurs liées à une expression peuvent se révéler lors de l’analyse de l’expression ou de son évaluation :

exp = QgsExpression("1 + 1 = 2")
if exp.hasParserError():
   raise Exception(exp.parserErrorString())

value = exp.evaluate()
if exp.hasEvalError():
   raise ValueError(exp.evalErrorString())