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)`
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?
    – Spacedman
    Apr 9, 2021 at 7:37
  • 1
    @BERA , Thanks a mill, both are working: For a date fieldtype and For a string field. Apr 9, 2021 at 12:17

1 Answer 1

7

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

Your Answer

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

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