Wednesday, 13 April 2016

qgis - Updating field with layer name on multiple layers with PyQGIS script?


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()

Answer



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()

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...