0

UPDATE In the code it needs to be f[realV] , so:

    with edit(lyr):
        for f in lyr.selectedFeatures():
            f[realV] = QgsExpression(str(doString))


I would like to update multiple features and multiple attributes with values, which are in the same layer. However, with the following code, nothing happens, I not even get an error message and so I don't know, why the features do not update.

This is my code:

# string values, in the form of decimals like '13.777'
fieldnames = [
                'MD_str',
                'MN_str',
                'ME_str',

                'PL1D_str',
                'PL1N_str',
                'PL1E_str',

                'PL2D_str',
                'PL2N_str',
                'PL2E_str'
                ]


# empty fields of type 'real'
real_fields = [
    'MD_r',
    'MN_r',
    'ME_r',

    'PL1D_r',
    'PL1N_r',
    'PL1E_r',

    'PL2D_r',
    'PL2N_r',
    'PL2E_r'
]

# Create tuple
dict_real =  list(zip(real_fields, fieldnames))

for pair in dict_real:
    realV = pair[0]
    strV = pair[1]
    
    doString = f"to_real(\"{strV}\")"

    with edit(lyr):
        for f in lyr.selectedFeatures():
            realV = QgsExpression(str(doString)) # correction:f[realV]
            lyr.updateFeature(f)

Does someone know, what I'm not doing correctly?

3
  • You are creating a QgsExpression but you never evaluate it. Also you never try to set any attribute value. Check qgis.org/pyqgis/3.22/core/QgsExpression.html and gis.stackexchange.com/a/403397/51035 Commented Jun 22, 2023 at 14:00
  • I just have found the error. It needs to be ``` f[realV] = qgsExpression(str(doString))```. Oh boy ... I worked on this quite a while. Probably its the very hot weather here today.
    – i.i.k.
    Commented Jun 22, 2023 at 14:16
  • @bugmenot123 Thank you for trying to help me! But I must say, I did not quite understand your answer. What do you mean by 'evaluating the QgsExpression' and 'never try to set any attribute value'?
    – i.i.k.
    Commented Jun 22, 2023 at 14:27

1 Answer 1

1

I had the chance to actually update my code and try it out. First of all, you need to know that it is not possible to transform a variable to another data type, for example from string to integer(see here: PyQGIS: Convert string variable to number format WITHOUT creating a new variable).

So you will always have two variables in the end, one string one numeric. Most importantly, I do not even need to use QgisExpression, but a simple equal was doing the job.

Steps to update multiple attributes are as follows:

  1. Create new ('empty') columns of the type you need the new variable in, e.g. into type integer. As I have multiple columns I first create a list of fieldnames by adding '_n' (for 'new') to the names of the fields I want to convert to another data type.
# First create names for the new fields by adding '_n' to the fieldnames
# you want to convert
 
fieldsToConvert = ['fn1','fn2', ... ]
fieldsNEW = [name + '_n' for name in fieldsStr] # 'fn1' will be 'fn1_n'
  1. Create new fields with the just created new names and specify the datatype you want the new variables to be in. Here, the new columns are of datatype integer (QVariant.Int)
lyr = iface.activeLayer()
lyr.startEditing()
for name in fieldsNEW:
     lyr.dataProvider().addAttributes([QgsField(name, QVariant.Int)])
     lyr.updateFields()

  1. I then create a dict with tuples of strings, in which each tuple contains the name of the variable which should be converted and the name of the corresponding new variable.
dict_fields = list(zip(fieldsToConvert, fieldsNEW)) # creates :[('fn1','fn1_n'),('fn2','fn2_n'), ... ]
  1. Update the fields by iterating over the dict and over the features. If you have a lot of features, there are other, more performant techniques than iterating and updating each feature.
# Iterate the dict of fieldnames
for pair in dict_fields:
    oldV = pair[0]
    newV = pair[1]

    # Put the active layer in edit mode and update the features
    with edit(lyr):
        for f in lyr.getFeatures():
            f[newV] = f[oldV]
            lyr.updateFeature(f)

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.