# Iterate over all attributes in QGIS Graphical Modeler

I would like to iterate over N unknown attributes in the QGIS Graphical Modeler. For example dividing all attributes in an input layer by its area to create an area weighting.

I realise it could be done with Python, but I'm wondering if there is some clever way to accomplish this with out-of-the-box tools.

• You can do that by using the Field Calculator. – geoSAM Oct 17 '19 at 7:12
• @geoSAM Okey, interesting, could you write an example as an answer? – hexamon Oct 17 '19 at 7:18
• One of the inputs is called "field mapper," which sounds promising. I can't find any documentation or figure out how it works though. – csk Oct 17 '19 at 16:08
• Or you could add as many `vector field` inputs as the maximum possible number of fields, then manually select them when you run the model. – csk Oct 17 '19 at 16:08
• see if this helps you gis.stackexchange.com/questions/292324/… – Herbert Santos Oct 18 '19 at 14:36

You can do that by using the sum function from the Field Calculator. Specifically for your case let's assume that you have a polygon vector with an attribute "AREA" representing the area of each polygon. In Field Calculator you create a new field with expression : `"AREA"/sum("AREA")`

• Ah, the key word in my question is unknown however. I want to iterate over all attributes in a layer without knowing their names and data types. So basically a for each loop where I do something with each attribute in a layer, and where the number of attributes and their names are unknown. – hexamon Oct 18 '19 at 7:18

I ended up writing a Python script after all. It's available here:

https://github.com/hexamon/qgispythonprocessing/blob/master/math_on_all_fields.py

If someone answers with a non-Python solution that works I will accept that instead.

Here is the relevant logic in the script:

``````    op = self.parameterAsEnum(parameters, self.OPERATION,context) #Math operation type fetched from enumerated list parameter
col = self.parameterAsFields(parameters, self.DIVCOL,context) #Column for operation

for current, feature in enumerate(features):

# Stop the algorithm if cancel button has been clicked
if feedback.isCanceled():
break

#Iterate over all fields
for current, attr in enumerate(feature.fields()):

#Don't process the column used for the operation
if current != feature.fieldNameIndex(col):

#Current attribute in iteration
c = feature.attribute(feature.fieldNameIndex(attr.name()))
#Column to use for operation
d = feature.attribute(feature.fieldNameIndex(col))

if(attr.isNumeric() == TRUE):

if(op == 0):
newVal = c * d
elif(op == 1):
newVal = c / d
elif(op == 2):
newVal = c + d
elif(op == 3):
newVal = c - d

feature.setAttribute(current, newVal)
``````