3

Introduction : I created (with GIS.SE help) a script to batch edit many layers to add one or many fields. The initial aim was to easily add 3 fields to many layers to quicken my labelling process. Example below :

Example

Below the initial code to start the script

##Perso=group
##Add_Labelling_Fields=name

##layer=multiple vector
##Field_ETIKT_X=string ETIKT_X
##Field_ETIKT_Y=string ETIKT_Y
##Field_ETIKT_ROT=string ETIKT_ROTATE

from osgeo import ogr

layers= layer.split(";")

for i in layers:
    driver = ogr.GetDriverByName('ESRI Shapefile')
    dataSource = driver.Open(i, 1) #1 is read/write

Actual problem : I'm now trying to find a way to create another similar script to batch update a field on many layers with the following expression : @layer_name to keep a track on where my data comes from, prior to merging multiple layers. It should also be a good way to add various calculations to many fields at once.

My problem here is similar as before : batch processing on editing a field does work with QGIS (through the processing toolboxes), but it creates new layers. I'd like to find the same type of script where you select many layers and it updates a field on all layers without creating new layers.

I tried a few things but I'm not really good with pyqgis yet and I get mixed up with the ways of updating fields depending on where the layer is declared from. There seems to be lots of different ways to do the same thing. No hurry for me, i can manage with other softwares (ex : FME) to do the trick but I think this could be useful for the many people that don't have those expensive softwares.

A this point, I don't exactly know how to call my layer and edit the attributes. I found this topic, but I don't exactly know how to fit them in my code...

it = layer.getFeatures()

layer.startEditing()
for feat in it:
  layer.changeAttributeValue(feat.id(), 2, 30)

layer.commitChanges()
0

1 Answer 1

7

Just happens that I created a script for a very similar thing recently (my script merges multiple layers into a new layer, while adding a new attribute to each feature describing where it stems from; this would be more in line with what you apparently intend to do in the future). I slashed the write-to-new-merged-layer part so it solves your question.

The script iterates over multiple vector layers of your choice, then adds the new field with field_name, unless this field already exists. After making sure this field exists, it then iterates over all features, applying the layer.name() to it. This is done inside an edit session, so all the changes are only applied when layer.commitChanges() is reached. This is both a safety and a performance measure.

NOTE: This is on QGIS 2.18.5.

##input_layers=multiple vector
##field_name=string
##General Tools=group
##layername as field=name

from qgis.core import *
from PyQt4.QtCore import QVariant

input_layers = input_layers.split(';')
for i in input_layers:
    layer = processing.getObject(i)

    if layer.fieldNameIndex(field_name) == -1:
        layer.dataProvider().addAttributes([QgsField(field_name, QVariant.String)])
        layer.updateFields()
    name = layer.name()
    layer.startEditing()
    for f in layer.getFeatures():
        #f[field_name] = layer.name() # NOTE: This should work, but for some reason doesn't. To manipulate feature attributes, always use the below method! Maybe QGIS3 will fix this :) .
        layer.changeAttributeValue(f.id(), layer.fieldNameIndex(field_name), name)
    layer.commitChanges()
3
  • That's a very nice script, thank you a lot ! (I'm going to learn from that). Could you add the slashed part as a comment if it's possible ? I'd be very interested to have the whole thing too :) Or I can ask another question, maybe it would be better....
    – gisnside
    Commented Apr 13, 2017 at 12:19
  • Glad to help! I'm afraid the slashed part would bust the limit of a comment, as it required a variety of quirks to work around. for example, my layers had varying number of fields, and I did not want to alter the original layers, but only add the "layer" field to the newly written one. Stuff like that requires some workarounds. Feel free to link/ @ me if you have trouble with this or another related question!
    – Senshi
    Commented Apr 13, 2017 at 12:27
  • this was just perfect. It shows me in this way a better way to update and created a field (good demonstration for the beginner in pyqgis I am). I'll probably reuse it in my previous script as it's much more clear to me me than what I did previously.
    – gisnside
    Commented Apr 13, 2017 at 12:37

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