1

I have a polygon layer, I want to fill the fields automatically each creation of a polygon.

Knowing that there is a spatial relationship (intersection, contain ...) between my polygons and other layers of point, the idea is to fill the fields instantaneously by the information from the point layers contained in the polygons.

Could someone help me on this subject ?

Setting up an action in layer properties seems possible, but how?

2 Answers 2

6

Please take a look at the aggregate function of the field-calculator.

In the layer properties the tab attribute form (8th from the top) you may set standard/preset values for your fields, e.g. based on field calculator formulas.

enter image description here

3
  • Thank you @Erik, Manually, it seems to work, but that's not the problem ! The problem is the instantaneous filling during the creation of each polygon features. Thank you.
    – Naslar
    May 7, 2019 at 15:45
  • Yeah, but this is exactly what you seem to want. This fills a features attributes on creation.
    – Erik
    May 8, 2019 at 6:42
  • 1
    Sorry Erik, I answered you hastily without even testing your solution. But rest assured, I tried it this morning, it works perfectly and responds well to my request. Thanks again !
    – Naslar
    May 8, 2019 at 7:22
4

QGIS 3.6.2 - Noosa

This will generate a memory layer of a spatial join between the polygon layer being edited and an existing points layer. The fields to be joined can be specified with the JOIN_FIELDS option.

The function is fired when editing a shape is finished (right-click during editing). It saves the edits made (commitChanges()) and then performs the join by location.

pnts = QgsProject.instance().mapLayersByName('points')[0]
poly = QgsProject.instance().mapLayersByName('polygons')[0]

def join_on_edit():
    # save edits made to the polygon layer
    poly.commitChanges()
    # remove any layers called 'joined_attributes' (prevents outputs stacking up)
    for lyr in QgsProject.instance().mapLayers().values():
        if lyr.name() == 'joined_attributes':
            QgsProject.instance().removeMapLayer(lyr)
    # proceed only if the layer being edited has any features (prevents an empty results layer being created if all features from poly layer are deleted)
    if len(list(poly.getFeatures())) > 0:
        # join by location using an intersect predicate
        l = processing.run("qgis:joinattributesbylocation", {'INPUT':poly,'JOIN':pnts,'PREDICATE':[0],'JOIN_FIELDS':[],'METHOD':0,'DISCARD_NONMATCHING':False,'PREFIX':'','OUTPUT':'memory:joined_attributes'})
        # add the memory layer result
        QgsProject.instance().addMapLayer(l['OUTPUT'])
        # active layer switches to newly created join by location layer so this reverts focus to editing layer
        iface.setActiveLayer(poly)
        # re-open the edit session
        poly.startEditing()
        # 'click' the add feature button in the digitizing toolbar for continuation of editing
        for a in iface.mainWindow().children():
            if a.objectName() == 'mActionAddFeature':
                a.trigger()
                break
  
# connect the layerModified signal with the function
poly.layerModified.connect(join_on_edit)
3
  • I try this method with the same code, but I have an error message : @AttributeError: 'QgsProject' object has no attribute 'mapLayersByName'
    – Naslar
    May 8, 2019 at 9:05
  • Which version of QGIS are you using? My apologies, I didn't specify mine in my answer. Now updated.
    – Matt
    May 8, 2019 at 9:36
  • I use 2.18 on my workstation, but the 3.4 on my personal computer, and it works perfectly. Thank you Now, I want to implement it either by means of an action (properties of the layer), or by a button, how to make it ? To read to you,
    – Naslar
    May 8, 2019 at 17:22

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.