7

I am building an expression, whose function is to return True if a characteristic is selected.

The expression requires two arguments, the Feature and the name of the layer.

If I enter the name of the layer as text it works properly. But if I enter a field containing the name of the layer it does not work, even if the record contains exactly the name.

Here is the code of the expression:

from qgis.core import *
from qgis.gui import *
from qgis.utils import iface

@qgsfunction(args='auto', group='Custom')
def isSelected(entidad, capa, feature, parent):
    proy= QgsProject.instance()
    capap= proy.mapLayersByName(capa)[0]
    les= list(capap.getSelectedFeatures())
    boolean=False
    for f in les:
        if f.id() == entidad.id():
            boolean= True
            break
        else:
            continue
    return boolean

Note:

  • The equivalent function, exists (is_selected) but does not work properly in my QGIS, version 3.4
  • The code works properly on the console
2
  • 1
    Probably the last thing you want to hear, but in 3.16 this works as expected, both with isSelected( $currentfeature, "<fieldname>" ) notation as well as isSelected( $currentfeature, attribute( '<fieldname>' ) ), where the field <fieldname> holds a string literal with a valid layer name. Are you certain your literals are not wrapped in any way? Did the internals for mapLayersByName change in any way between versions, removing or adding wrapping characters?
    – geozelot
    Dec 31, 2020 at 9:56
  • 1
    Also, what exactly 'does not work'? Any errors?
    – geozelot
    Dec 31, 2020 at 10:02

2 Answers 2

5

I found a solution worked for me.

  • Add this script to the "Function Editor":
from qgis.core import *
from qgis.gui import *

@qgsfunction(args='auto', group='Custom')
def isSelected(feat, field, feature, parent):
    layer = QgsProject.instance().mapLayersByName(field)[0]
    for f in layer.getSelectedFeatures():
        if f['fid'] == feat['fid']:
            return 1 # True
    return 0 # False
  • Run this expression for layer A (see the picture below):
isSelected(
  get_feature('C', 'fid', "fid"),
  lyr_field
)

Explanation:

  • get_feature('C', 'fid', "fid"):

    Return the feature of C matching (fid in C == "fid" in A)

  • QgsProject.instance().mapLayersByName(field)[0]:

    Return the layer matching the lyr_field value (B here) of the feature in A.

  • layer.getSelectedFeatures():

    Get selected features in B.

  • if f['fid'] == feat['fid']:

    If fid value of one of the selected features in B exists in C then return 1, else return 0

If get_feature('C', 'fid', "fid") returns None, the expression returns nothing.

I used aa field to populate.

enter image description here

1
  • I'm confused, too. I hope I didn't write anything wrong. :) Jan 1, 2021 at 22:45
4

See below the changed code: you will not need the parameter "entidad" you can use the default parameter "feature" instead:

from qgis.core import *
from qgis.gui import *
from qgis.utils import iface

@qgsfunction(args='auto', group='Custom')
def isSelected(capa, feature, parent):
    proy= QgsProject.instance()
    capap= proy.mapLayersByName(capa)[0]
    les= list(capap.getSelectedFeatures())
    boolean=False
    for f in les:
        if f.id() == feature.id():
            boolean= True
            break
        else:
            continue
    return boolean
1
  • Thanks for the suggestion, but feature can be specified or is it a feature of the layer on which the expression is performed? The idea is to apply an aggregate expression, the entity variable is a feature of a layer different from the current one
    – Luis Perez
    Dec 3, 2020 at 11:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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