3

I would like to get an array with IDs of all selected features of layer 'LayerB' (field-name: "id_of_layerB") as a default value in a QGIS Attribute form of 'LayerA'.

I tried something like:

aggregate(layer:='LayerB',
          aggregate:='array_agg',
          expression:= "id_of_layerB",
          is_selected('LayerB', ???)
          )

but I have no idea how to realize this (especially what to put in the ???-part of the expression part of the code.

I think, the is_selected()-function checks agains just one feature, but is there a way to get ALL (one or more) selected features of 'LayerB'?

6 Answers 6

2

Try to adjust your expression like this:

string_to_array(
    aggregate(@layer,
              aggregate:='concatenate',
              expression:=to_string("id"),
              filter:=is_selected(),
              concatenator:=','),
    delimiter:=',')

result3

1
  • I've no idea why code works just in some layers in my project. There are several layers where code does not work (type: character varying[]). Same code is copied from one layer and its fieldcalculator to another by copy and paste with different results/previews:['1','2'...] or ['']
    – user191847
    Nov 24, 2020 at 20:32
2

Used the pyqgis-code from @Taras, renamed some arguments and added some flexibility (layerName as argument) and a check against unique layername and added a helptext :

from qgis.core import *
from qgis.gui import *


@qgsfunction(args='auto', group='Custom')

def selected_content(layerName, field, feature, parent):
    """
    Returns a array of field-contents of selected features<br><br>
    Returns <br><br><span class=\"argument\">string </span>Array of field-contents
    <br>
    <h4>Syntax</h4><br>
    <code><span class=\"functionname\">selected_features</span> <span class=\"argument\">(string, string)</span></code><br>
    
    <h4>Arguments</h4><br>    
    <span class=\"argument\">string </span>UNIQUE layer name <br>
    <span class=\"argument\">integer </span>field name <br>
    <h4>Example</h4><br>    
    <ul> 
      <li><code>selected_content('myLayerName','myFieldName')</code> &rarr; <code>'['a','b']'</code>
    </ul>

    """
    layer = layers = QgsProject.instance().mapLayersByName(layerName)
    if len(layer)>1:
        content=['invalid layer name (not unique)']
    else:
        selection = layer[0].selectedFeatures()
        content = [feature[field] for feature in selection]
    return content
2

One can also apply the concatenate() function:

string_to_array(
    concatenate(
        to_string("id"),
        filter:=is_selected(),
        concatenator:=','
        ),
    delimiter:=',')

result1

1
  • I'd prefer your first approach (string_to_array(aggregate(@layer...) because the array shall be stored in another layer
    – user191847
    Nov 24, 2020 at 20:37
2

Alternatively, one may try using a short PyQGIS code:

layer = iface.activeLayer()
selection = layer.selectedFeatures()
ids = [feature['id'] for feature in selection]

result

1
  • But how to add this code in a expession? Modifed code. But still does not work: aggregate( layer:= 'LayerB', aggregate:='array_agg', expression:="id_of_layerB", filter:=is_selected('LayerB' , get_feature_by_id('LayerB',$id))=True)
    – user191847
    Nov 23, 2020 at 9:34
2

Another possible expression:

array_filter(
    array_foreach(generate_series(0, layer_property(@layer, 'feature_count')-1),
        if(is_selected(get_feature_by_id(@layer, @element)), attribute(get_feature_by_id(@layer, @element), 'id'),'***')
        ),
    @element != '***')

result2

2
  • seems to have a slower performance on large layers
    – user191847
    Nov 24, 2020 at 20:40
  • yes, you are right. because it involves a bit more functions than other approaches
    – Taras
    Nov 24, 2020 at 20:41
2

Or you can use Python in the Field Calculator via the Function Editor

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

@qgsfunction(args='auto', group='Custom')
def ids(field, feature, parent):
    layer = iface.activeLayer()
    selection = layer.selectedFeatures()
    ids = [feature[field] for feature in selection]
    return ids

python

and get the output

result

Note: That function ids('id') reads field with a single parenthesis i.e. '.

2
  • I'd prefer your first approach (string_to_array(aggregate(@layer...) because the layer may not be selected in my case
    – user191847
    Nov 24, 2020 at 20:38
  • Shall I delete other solutions that are not working for you?
    – Taras
    Nov 24, 2020 at 20:39

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.