QGIS – Using Layer Variables in Rule-Based Styling Query Builder

expressionpyqgis-3qgisqgis-processing

I want to make an "Action" in QGIS 3.16 that enables me quickly to style features I select in the rule-based styling.

The action code below produces a string of the selected features, and saves them in a layer variable.

layer_id = '[%@layer_id%]'
layer = QgsProject().instance().mapLayer(layer_id)

list = []

for feature in layer.selectedFeatures():
    list.append(feature['myfeature'])

string1 = str(list)[1:-1]
string2 = "(" + string1 + ")"

QgsExpressionContextUtils.setLayerVariable(layer,'variablename',string2)

This piece of codes works well and produces a string like this example:

(1072566, 1072375, 9400438, 1072569, 3241157, 1072376)

In the query builder, I want to make a filter based on the variable, like this:

"myfeature" IN (@variablename)

Unfortunately, this doesn't work.

When I test the filter, it tells me that no features are returned.

But if I copy the output string, it works:

"myfeature" IN (1072566, 1072375, 9400438, 1072569, 3241157, 1072376)

and when I only enter

@variablename

I can see in the bottom of the Query Builder window, that it returns the correct string to use in an IN-clause.

Can anyone help me?

Best Answer

When you are using this expression "myfeature" IN (1072566, 1072375, 9400438, 1072569, 3241157, 1072376) you are comparing an integer to an array of integer that's why it works. When you are using this expression "myfeature" IN ("variablename") you are comparing an integer to a string, so it wont work. You need to create an array of string and convert your integer as a string.

You should create your string without parenthesis like this '1072566, 1072375, 9400438, 1072569, 3241157, 1072376'. And then create an array based on this string in the query builder with the function string_to_array, string_to_array("variablename", ', '). Your array will look like this ['1072566', '1072375', '9400438', '1072569', '3241157', '1072376'], it's an array of string.

"myfeature" needs to be a string aswell, you can use the function to_string, to_string("myfeature")

Finally, to compare an array and a value you can use the function array_contains,array_contains(string_to_array("variablename", ', '),to_string("myfeature"))

Related Question