Os trechos de código desta página precisam das seguintes importações se você estiver fora do console do pyqgis:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from qgis.core import (
    edit,
    QgsExpression,
    QgsExpressionContext,
    QgsFeature,
    QgsFeatureRequest,
    QgsField,
    QgsFields,
    QgsVectorLayer,
    QgsPointXY,
    QgsGeometry,
    QgsProject,
    QgsExpressionContextUtils
)

11. Expressões, filtragem e cálculo dos valores

O QGIS possui alguns recursos para análise de expressões semelhantes à SQL. Apenas um pequeno subconjunto da sintaxe SQL é suportado. As expressões podem ser avaliadas tanto como predicados booleanos (retornando Verdadeiro ou Falso) ou como funções (retornando um valor escalar) . Veja Expressões no Manual do Usuário para uma lista completa das funções disponíveis.

Três tipos básicos são suportados:

  • número — ambos os números inteiros e números decimais, por exemplo, 123, 3.14

  • texto — eles devem estar entre aspas simples: ‘Olá world’`

  • coluna referência — ao avaliar, a referência é substituída com o valor real do campo. Os nomes não alteram.

As seguintes operações estão disponíveis:

  • operadores aritméticos: +, -, *, /, ^

  • parênteses: para fazer cumprir a precedência do operador: (1 + 1) * 3

  • Sinal mais e menos: -12, +5

  • funções matemáticas: sqrt, sen, cos, tan, asen, acos, atan

  • Funções de conversão: “to_int”, “to_real”, “to_string”, “to_date”

  • funções geométricas: $area, $length

  • funções de manipulação de geometria: “$x”, “$y”, “$geometry”, “num_geometries”, “centroid”

E os seguintes predicados são suportados:

  • comparação: =, !=, >, >=, <, <=

  • correspondência padrão: LIKE (usando % e _), ~ (expressões regulares)

  • predicados lógicos: AND, OR, NOT

  • verificação de valor nulo: IS NULL, IS NOT NULL

Exemplos de predicados:

  • 1 + 2 = 3

  • sen(ângulo) > 0

  • 'Hello' LIKE 'He%'

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

Exemplos de expressões escalares:

  • 2 ^ 10

  • sqrt(val)

  • $length + 1

11.1. Expressões de Análise

O exemplo a seguir mostra como verificar se uma determinada expressão pode ser analisada corretamente:

1
2
3
4
5
6
7
exp = QgsExpression('1 + 1 = 2')
assert(not exp.hasParserError())

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

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

11.2. Expressões de Avaliação

Expressões podem ser usadas em diferentes contextos, por exemplo, para filtrar recursos ou calcular novos valores de campo. De qualquer forma, a expressão deve ser avaliada. Isso significa que seu valor é calculado executando as etapas computacionais especificadas, que podem variar de aritmética simples a expressões agregadas.

11.2.1. Expressões Básicas

Essa expressão básica é avaliada como 1, o que significa que é verdadeiro:

exp = QgsExpression('1 + 1 = 2')
assert(exp.evaluate()) # exp.evaluate() returns 1 and assert() recognizes this as True

11.2.2. Expressões com características

Para avaliar uma expressão em relação a um recurso, um objeto QgsExpressionContext deve ser criado e passado à função de avaliação para permitir que a expressão acesse os valores de campo do recurso.

O exemplo a seguir mostra como criar um recurso com um campo chamado “Coluna” e como adicionar esse recurso ao contexto da expressão.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
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)

A seguir, é apresentado um exemplo mais completo de como usar expressões no contexto de uma camada vetorial, para calcular novos valores de campo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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'])
876.5

11.2.3. Filtrando uma camada com expressões

O exemplo seguinte pode ser usado para filtrar uma camada e devolver qualquer característica que corresponda a um predicado.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
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)

11.3. Manipulando erros de expressão

Erros relacionados à expressão podem ocorrer durante a análise ou análise de expressão:

1
2
3
4
5
6
7
exp = QgsExpression("1 + 1 = 2")
if exp.hasParserError():
   raise Exception(exp.parserErrorString())

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