4

In QGIS 2.14 one can check if a rule gives results:

enter image description here

Is it possible to do this programmatically with python console? I would look for a way to iterate over all layers and there rules (nested rules!) and print those (layer_name:rule_name) which do not have results.

3

Perhaps this answer can fully solve your question.

Run this code snippet in the QGIS Python Console:

for layer in QgsMapLayerRegistry.instance().mapLayers().values(): # Iterate layers
    if type(layer) == QgsVectorLayer and layer.hasGeometryType():
        r = layer.rendererV2()
        if r.type() == 'RuleRenderer':
            for rule in r.rootRule().children(): # Iterate rules
                if rule.filter(): # Filter out empty rules
                    request = QgsFeatureRequest( rule.filter() )
                    count = len( [f for f in layer.getFeatures( request )] )
                    print layer.name() + ' : ' + rule.label() + ' : ' + rule.filterExpression() + ' : ' + str(count)

The first for loop iterates layers, the second one iterates layer rules. First if clause ensures we use vector layers, the second one ensures we only use vector layers with a rule based style, and the last one filters out empty rules.

The result is a list with layer names, rule labels, rule expressions, and the corresponding count, like this:

my_point_layer : My Rule :  "my_code" = '1': 6
my_point_layer : My 2nd Rule :  "my_code" IS NULL : 0
my_polygon_layer : My Polygon Rule :  "area" > 100 : 2
my_polygon_layer : My 2nd Polygon Rule :  "area <= 100 : 28

You could then use the count variable to filter only those with 0 features, which was your original purpose.

Hope this solves your question.

  • 1
    Hey Germán this looks to good to be true! Unfortuantely I´m getting an error: http://hastebin.com/akuvilizaq.py. Do you know what´s going wrong here? – t Book Sep 13 '16 at 9:44
  • Thanks for the feedback. I didn't test the original code with empty rules (those with no filter), but I've now updated the answer to take them into account. If you face any other problem, just tell me, we're approaching the solution. – Germán Carrillo Sep 13 '16 at 12:31
  • 1
    WHOOO WHOOO. GENIOUS! This works just great! Many many thanks! – t Book Sep 13 '16 at 12:55
  • Great! Glad to have helped you somehow. – Germán Carrillo Sep 13 '16 at 13:08
  • 1
    Germán this is pure magic! It´s working. Now it´s clear I have to learn more python! thanks you really a lot! – t Book Sep 13 '16 at 19:31
3

It's a simple selection:

for layer in layers:
    expression = QgsExpression("your expression goes here")
    features = layer.getFeatures(QgsFeatureRequest(expression))
    number_of_features = sum(1 for _ in features) # you should count this in that way beacuse this object is an iterator
    print "Number of features found: " + str(number_of_features)

Edit:

If you have many rules (the same set of rules for each layer) add another iteration:

for layer in layers:
    for rule in rules: # assumed that rules = ["rule 1", "rule 2", ...]
        expression = QgsExpression("your expression goes here")
        features = layer.getFeatures(QgsFeatureRequest(expression))
        number_of_features = sum(1 for _ in features)
        if not number_of_features:
            print rule

If you have many rules different for each layer, maybe organise them in a dictionary:

rules = {"layer1": ["rule 1", "rule 2"], "layer2": ["rule 3", "rule 4"]}

for layer in layers:
    r = rules[layer.name()]
    for rule in r: 
        expression = QgsExpression("your expression goes here")
        features = layer.getFeatures(QgsFeatureRequest(expression))
        number_of_features = sum(1 for _ in features)
        if not number_of_features:
            print rule
  • dmh126 thanks for your reply! Your solution assumes I always have the same expression for all layers/rules, right? But the case if different. I have about 100 Layers each has already ~10 rules and I´d like to now which of these rules are obselete. – t Book Sep 7 '16 at 7:20
  • I've edited my post with new solution to your problem. – dmh126 Sep 7 '16 at 9:28
  • 1
    Hi dmh126, thanks a lot for your really useful answer. Even if it´s not exactly what I need I accept this as answer. My problem is that I do not know which rules are there. When using a dictionary I have to open every layer look for each expression and copy it. It´s the same time when just pressing the "test" button. That´s why I thought python can help here and iterate over all existing expressions. Anyway as said this is really really useful for me for future projects. thanks! – t Book Sep 8 '16 at 8:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.