I have dozens of layers in QGIS and all these layers have attribute field that I would like to update. I don't want to create new temporal layers with updated fields, rather just update the current layer attribute tables. And I wouldn't want to separately update each layer. I tried field calculator but it creates a new temporal layer. Is there any other solutions that could work? I'm using QGIS 3.22.
-
Using field calculator, you have an option to update existing fields. Field calculator does not create new layers, why do you think it does? Describe your workflow and add a screenshot to understand what's going on...– BabelDec 21, 2021 at 7:51
-
Field name is 'Modified' and I would need to update the field with a date when the layer have been updated. I'm not familiar with pyqgis but I'm afraid that I won't be able to use that as I would first need to be able to select the layers that have been modified in 1st of December and then update these layers with that date and then I would need to select layers that have been modified in 3rd of December and so on. The modification date is in the layer name.– Q-questionDec 21, 2021 at 7:56
-
I tried with field calculator and it created this 'calculated' temporal layer. How can I set the field calculator so that it does not create a temporal layer? Then I could run as a batch process and it probably could work for this.– Q-questionDec 21, 2021 at 8:19
-
Sorry, can you show a screenshot where filed calculator creates a new temporary layer? My field calculator does not! To update an existing field, check the box next to that, see: i.stack.imgur.com/aaffO.png– BabelDec 21, 2021 at 8:43
-
1I added screenshot to my first message. Which version do you use? I noticed that in QGIS 3.4.3 there is option for updating an existing field, but unfortunately there is no option for running as a batch process, so probably is not solution for me in this case.– Q-questionDec 21, 2021 at 8:47
1 Answer
You can use pyqgis with re (to find the date) and datetime (to format the date) modules.
The layers must have a 8 digit date somewhere in the layername, formatted like 20211221 (YYYYMMDD). Try it on a subset of layers and backup your data first.
import re, datetime
fieldname = 'modified' #A string field that must exist in each table, change to match your fieldname
patt = r'\d{8}' #Search layername for 8 consecutive digits
for layer in QgsProject.instance().mapLayers().values(): #For each layer added to QGIS
attrMap = {} #A dictionary to hold feature id: fieldindex:new value
found = re.search(patt, layer.name()) #Find the 8 digits in a row
fieldindex = layer.fields().indexFromName(fieldname) #Find the index of "modified" field
if found:
oldval = datetime.datetime.strptime(found.group(), '%Y%m%d') #datetime.datetime(2021, 11, 12, 0, 0) #Create a datetime object
newval = datetime.datetime.strftime(oldval, '%m%d%Y') #Convert to a string in the format you want
for f in layer.getFeatures():
attrMap[f.id()] = {fieldindex:newval}
layer.dataProvider().changeAttributeValues(attrMap)