5

I have a folder with several shapefiles (around 75). I would like to create a new field into each .shp file which has to be filename. i.e: 20201003.shp --> 20200103.shp (New field 'Fecha' = 20200103)

I have tried this but nothing is done and no errors neither:

import os, datetime
`shapefolder = r'C:\Users\juavafer\Proyectos\Costas_CoastSat\Output\CMillor\Comparacion\matlab\Qgis'
newfieldname = 'test3'
for root, folder, files in os.walk(shapefolder):
 #Find the shapefile
 for file in files:
 fullpath = os.path.join(root,file)
 if os.path.isfile(fullpath) and fullpath.endswith('.shp'):
 print(fullpath)
 #Extract numbers from filename
 datename = ''.join([num for num in file if num.isdigit()])
 #Create a datetime object and convert to string in format 'YYYY-MM-DD', which is what a shapefile wants
 QgsField(name='test3', type=QVariant.String, len=20)
 newdatename = dt.strftime('%Y%m%d')
 
 print(datename)
 # dt = datetime.datetime.strptime(datename, '%Y%m%d')
 # newdatename = dt.strftime('%Y%m%d')
 print(datename)
 #Add the field https://opensourceoptions.com/blog/pyqgis-adding-and-deleting-vector-layer-fields/
 layer = QgsVectorLayer(fullpath)
 layer.dataProvider().addAttributes([QgsField(newfieldname, QVariant.Date)])
 layer.updateFields()
 
 #Update each feature with date https://gis.stackexchange.com/questions/381174/setting-all-the-values-in-a-attribute-field-to-the-same-value-with-pyqgis)
 attr_map = {}
 field_index = layer.fields().indexFromName(newfieldname)
 for f in layer.getFeatures():
 attr_map[f.id()] = {field_index: newdatename}
 layer.dataProvider().changeAttributeValues(attr_map)`
Bera
81.7k14 gold badges85 silver badges199 bronze badges
asked Apr 9, 2021 at 7:25
2
  • 1
    If you use the attribute table dialog and create a new field using the expression base_file_name(layer_property(@layer_id,'source')) you will get that. Not sure how to repeat that over 75 layers though. Note this requires the shapefiles to be loaded as layers to QGIS - have you got that? Commented Apr 9, 2021 at 7:37
  • 1
    @BERA , Thanks a mill, both are working: For a date fieldtype and For a string field. Commented Apr 9, 2021 at 12:17

1 Answer 1

8

You can use pyqgis.

For a date fieldtype:

import os, datetime
shapefolder = r'C:\GIS\data\folder' #Where you have your 75 shapefiles (and no other shapefiles, including in any subdirectories!)
newfieldname = 'fecha'
for root, folder, files in os.walk(shapefolder):
 #Find the shapefile
 for file in files:
 fullpath = os.path.join(root,file)
 if os.path.isfile(fullpath) and fullpath.endswith('.shp'):
 print(fullpath)
 #Extract numbers from filename
 datename = ''.join([num for num in file if num.isdigit()])
 #Create a datetime object and convert to string in format 'YYYY-MM-DD', which is what a shapefile wants
 dt = datetime.datetime.strptime(datename, '%Y%m%d')
 newdatename = dt.strftime('%Y-%m-%d')
 print(datename)
 #Add the field https://opensourceoptions.com/blog/pyqgis-adding-and-deleting-vector-layer-fields/
 layer = QgsVectorLayer(fullpath)
 layer.dataProvider().addAttributes([QgsField(newfieldname, QVariant.Date)])
 layer.updateFields()
 
 #Update each feature with date https://gis.stackexchange.com/questions/381174/setting-all-the-values-in-a-attribute-field-to-the-same-value-with-pyqgis)
 attr_map = {}
 field_index = layer.fields().indexFromName(newfieldname)
 for f in layer.getFeatures():
 attr_map[f.id()] = {field_index: newdatename}
 layer.dataProvider().changeAttributeValues(attr_map)

enter image description here

For a string field:

import os
shapefolder = r'C:\GIS\data\testdata\folder'
newfieldname = 'fecha'
for root, folder, files in os.walk(shapefolder):
 #Find the shapefile
 for file in files:
 fullpath = os.path.join(root,file)
 if os.path.isfile(fullpath) and fullpath.endswith('.shp'):
 print(fullpath)
 
 #Extract numbers from filename
 datestr = ''.join([num for num in file if num.isdigit()])
 print(datestr)
 
 #Add the field
 layer = QgsVectorLayer(fullpath)
 layer.dataProvider().addAttributes([QgsField(name=newfieldname, type=QVariant.String, len=10)])
 layer.updateFields()
 
 #Update each feature with date (in a fast way using an attribute map: https://gis.stackexchange.com/questions/381174/setting-all-the-values-in-a-attribute-field-to-the-same-value-with-pyqgis)
 attr_map = {}
 field_index = layer.fields().indexFromName(newfieldname)
 for f in layer.getFeatures():
 attr_map[f.id()] = {field_index: datestr}
 layer.dataProvider().changeAttributeValues(attr_map)
answered Apr 9, 2021 at 9:07
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.