3

I run a model with an if-condition with sucess. After exporting the code the scirpt gives me an error:

"Unable to execute algorithm Field name is not set. Please enter a field name"

The code-snippet seems to be okay

"""
Model exported as python.
Name : BlnField
Group : Test
With QGIS : 31100
"""

from qgis.core import QgsProcessing
from qgis.core import QgsProcessingAlgorithm
from qgis.core import QgsProcessingMultiStepFeedback
from qgis.core import QgsProcessingParameterBoolean
from qgis.core import QgsProcessingParameterVectorLayer
from qgis.core import QgsProcessingParameterFeatureSink
from qgis.core import QgsProcessingParameterDefinition
from qgis.core import QgsExpression
import processing


class Blnfield(QgsProcessingAlgorithm):

    def initAlgorithm(self, config=None):
        param = QgsProcessingParameterBoolean('blnF', 'Soll ein Feld "Fl_m²" angelegt und die Flächen berechnet werden?', optional=False, defaultValue=False)
        param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
        self.addParameter(param)
        self.addParameter(QgsProcessingParameterVectorLayer('l', 'l', types=[QgsProcessing.TypeVectorAnyGeometry], defaultValue=None))
        self.addParameter(QgsProcessingParameterFeatureSink('Resfc', 'Ergebnis:', type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, defaultValue=None))

    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(1, model_feedback)
        results = {}
        outputs = {}

        # Field calculator
        alg_params = {
            'FIELD_LENGTH': 10,
            'FIELD_NAME': QgsExpression(' if(@blnF ,\'Fl_m2\',\'\')').evaluate(),
            'FIELD_PRECISION': 3,
            'FIELD_TYPE': 1,
            'FORMULA': ' $area ',
            'INPUT': parameters['l'],
            'NEW_FIELD': True,
            'OUTPUT': parameters['Resfc']
        }
        outputs['FieldCalculator'] = processing.run('qgis:fieldcalculator', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
        results['Resfc'] = outputs['FieldCalculator']['OUTPUT']
        return results

    def name(self):
        return 'BlnField'

    def displayName(self):
        return 'BlnField'

    def group(self):
        return 'Test'

    def groupId(self):
        return 'Test'

    def createInstance(self):
        return Blnfield()

enter image description here

enter image description here

3
  • Please, paste your full code. By the number of 'OUTPUT' in the results, it seens to be more steps than showed. Commented Jan 16, 2020 at 12:39
  • @Herber Santos: above the picture is the complete code for copy and paste
    – kjp
    Commented Jan 16, 2020 at 13:13
  • The second image seems to show more steps than the pasted algorithm. Commented Jan 16, 2020 at 14:09

1 Answer 1

4

The error really is in field_name.

This field should be given a fixed name and not an expression, and your expression can generate an empty name inclusive. Try this:

'FIELD_NAME': 'AREA',

EDIT

Now I understand your purpose, this is not a solution to the error presented, but a solution to the use that is in the question you mentioned:

"""
Model exported as python.
Name : BlnField
Group : Test
With QGIS : 31100
"""

from qgis.core import QgsProcessing
from qgis.core import QgsProcessingAlgorithm
from qgis.core import QgsProcessingMultiStepFeedback
from qgis.core import QgsProcessingParameterBoolean
from qgis.core import QgsProcessingParameterVectorLayer
from qgis.core import QgsProcessingParameterFeatureSink
from qgis.core import QgsProcessingParameterDefinition
from qgis.core import QgsExpression
from qgis.core import QgsFeatureSink
import processing


class Blnfield(QgsProcessingAlgorithm):


    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterBoolean('blnF', 'Soll ein Feld "Fl_m²" angelegt und die Flächen berechnet werden?', optional=False, defaultValue=False))
        self.addParameter(QgsProcessingParameterVectorLayer('l', 'l', types=[QgsProcessing.TypeVectorAnyGeometry], defaultValue=None))
        self.addParameter(QgsProcessingParameterFeatureSink('Resfc', 'Ergebnis:', type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, defaultValue=None))

    def processAlgorithm(self, parameters, context, model_feedback):
        # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the
        # overall progress through the model
        feedback = QgsProcessingMultiStepFeedback(1, model_feedback)
        results = {}
        outputs = {}

        if parameters['blnF'] is True:

            # Field calculator
            alg_params = {
                'FIELD_LENGTH': 10,
                'FIELD_NAME': 'AREA',
                'FIELD_PRECISION': 3,
                'FIELD_TYPE': 1,
                'FORMULA': ' $area ',
                'INPUT': parameters['l'],
                'NEW_FIELD': True,
                'OUTPUT': parameters['Resfc']
            }
            outputs['FieldCalculator'] = processing.run('qgis:fieldcalculator', alg_params, context=context, feedback=feedback, is_child_algorithm=True)
            results['Resfc'] = outputs['FieldCalculator']['OUTPUT']

        else:

            source = self.parameterAsSource(parameters,'l',context)
            (sink, dest_id) = self.parameterAsSink(parameters,'Resfc',context,source.fields(),source.wkbType(),source.sourceCrs())
            total = 100.0 / source.featureCount() if source.featureCount() else 0
            features = source.getFeatures()
            for current, feature in enumerate(features):
                sink.addFeature(feature, QgsFeatureSink.FastInsert)
                feedback.setProgress(int(current * total))


        return {}

        return results

    def name(self):
        return 'BlnField2'

    def displayName(self):
        return 'BlnField2'

    def group(self):
        return 'Test'

    def groupId(self):
        return 'Test'

    def createInstance(self):
        return Blnfield()

Instead of testing the condition within the field calculator, test directly on the parameter, if yes the next step will be executed, otherwise the field calculator will be ignored.

EDIT (2)

New changes.

If the boolean is marked the polygon area will be calculated, otherwise the output will be the same as the input.

The idea and explanation for the process within ELSE is HERE.


Also modified the way the boolean was created, only to reduce lines and let the cleaner use of screen but does not have processing change.

8
  • but the code came from a model that does the job. See here gis.stackexchange.com/questions/347411/…
    – kjp
    Commented Jan 16, 2020 at 15:16
  • @kjp I believe now the answer satisfies Commented Jan 16, 2020 at 16:04
  • the code snipet runs, but if I use with other algorithm und the booelan value is false then it stops. how must be the else condition for following steps?
    – kjp
    Commented Jan 17, 2020 at 9:52
  • @kjp Tell me what this Boolean will do exactly so that I can build an example closer to your reality. Commented Jan 17, 2020 at 10:13
  • @HerbertSantos - I'm assuming the boolean is there if the user wants to add a new area field and if it is left unchecked, the output would be a temporary layer of the input layer.
    – Joseph
    Commented Jan 17, 2020 at 11:26

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.