2

I have some vector shape files with many columns. I need to change the name of each column in the header from the old name to a more generic "Img1", "Img2", "Img3", etc progressively, starting from column #5 and leaving the name of columns 1 to 4 unchanged.

I wrote this Python code to be used with QGIS but it doesn't work.

layer = iface.activeLayer()
nImg = 1
nCol = len(layer.pendingFields())
cont = (5,nCol)
for field in cont:
    with edit (layer):
        oldName = layer.fieldNameIndex(field.name())
        newName = "Img" + str(nImg)
        layer.renameAttribute(oldName, newName)
    nImg = + 1

The error is

oldName = layer.fieldNameIndex(field.name())
AttributeError: 'int' object has no attribute 'name'

I tried also changing

with edit (layer) 

to

layer.startEditing() 

and unindenting the rows, but it doesn't work anyway.

2
  • Please Edit the question to specify whether you are trying to change the field presentation associated with the layer or the actual column names in the source table.
    – Vince
    Dec 31, 2017 at 19:50
  • Hi Vince, I edited the text and I specified that I'm talking about shapefiles and I need to rename the header of the attribute tables. Cheers
    – ilFonta
    Jan 1, 2018 at 12:22

3 Answers 3

2

The error is thrown by this line:

oldName = layer.fieldNameIndex(field.name())

and it is saying that field is an integer not an object with a name method. Also checking the documentation shows that:

int QgsFeature::fieldNameIndex ( const QString & fieldName )
const Utility method to get attribute index from name.

Field map must be associated using setFields() before this method can be used.

Parameters fieldName name of field to get attribute index of Returns -1 if field does not exist or field map is not associated.

So it looks up the index of a field based on its name, but you want to find the name based on its index. To do this you need to grab the qgsFields map using the fields method. So something like:

fields = layer.fields()
for field in cont:
with edit (layer):
    oldName = fields.at(field).name()
    newName = "Img" + str(nImg)
    layer.renameAttribute(oldName, newName)
nImg = + 1
1

This is the code that works for my issue

layer = iface.activeLayer()
nImg = 1
startCol = 5
endCol = len(layer.pendingFields())
countCol = (range(startCol,endCol,1))
for colNumber in countCol:
    with edit (layer):
        newName = "Img" + str(nImg)
        layer.renameAttribute(colNumber, newName)
        nImg = nImg + 1
1

If your GIS data format is shapefile then you can change the field names using the DBF python library as the attributes are defined in the DBF file:

import dbf
layer = dbf.Table('dbf_file')
cont = layer.field_names
try:
    for oldName in cont:
        newName = "Img" + str(nImg)
        layer.rename_field(oldName, newName)
        nImg = + 1
finally:
    layer.close()
5
  • What if the dataset isn't shapefile?
    – Vince
    Jan 1, 2018 at 1:02
  • @Vince you are right, I missed that :(
    – Shiko
    Jan 1, 2018 at 1:06
  • dbf library seems good, but I couldn't make it working. I get this error message "raise DbfError('%s not in read/write mode, unable to change field names' % meta.filename)"
    – ilFonta
    Jan 1, 2018 at 19:40
  • @ilFonta you will need to use layer.open(mode=dbf.READ_WRITE) after reading the file .. se here stackoverflow.com/questions/49314270/cant-write-dbf-file Jan 28, 2022 at 10:47
  • I notice that dbf can only handle alphanumeric characters and _ in field names. Shape file however allows for other characters, such as () Jan 28, 2022 at 10:50

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.