0

I am trying to make a tool in which there are many sequence parameters (based on the same field of a feature class), and each of them is multi value to make a user choose from a check a list one or more value from values in this field.

If the same field's values I need to use in sequence parameters, but I want to avoid the duplication in selecting values in these sequence parameters, so how to adjust the validation code, so that if the user select definite value(s) in a parameter, that or these values can not be selected in the following parameter, unless that or these values are unselected in the previous parameters?

For example, if in a parameter the user select the value "Canada" based on a field for countries' names, I want to avoid the repeating of selecting the value "Canada" in a following parameter, that is also based on the same field for countries' names, unless the user return to the previous parameter and unselect or uncheck the value "Canada".


import arcpy
class ToolValidator(object):
    def __init__(self):         
       """Setup arcpy and the list of tool parameters."""
       self.params = arcpy.GetParameterInfo()

    def initializeParameters(self):

        """Refine the properties of a tool's parameters.  This method is
        called when the tool is opened."""
        return

    def updateParameters(self):
        if not params[0].value:
            """Modify the values and properties of parameters before internal
            validation is performed.  This method is called whenever a parameter
            has been changed."""
            global previousProjectPath3
            previousProjectPath3 = ""
            if self.params[1].value and self.params[3].value:
                self.params[4].filter.list = sorted({row[0] for row in arcpy.da.SearchCursor(self.params[1].value, self.params[3].value.value) if row[0]})
            if self.params[1].value and self.params[3].value:
                self.params[5].filter.list = sorted({row[0] for row in arcpy.da.SearchCursor(self.params[1].value, self.params[3].value.value) if row[0]})        

    def updateMessages(self):
        """Modify the messages created by internal validation for each tool
        parameter.  This method is called after internal validation."""
        if params[0].altered:
            path = params[0].valueAsText
            global previousProjectPath3
            if previousProjectPath3 != path:
                previousProjectPath3 = path
  • Welcome to GIS SE! As a new user be sure to take the Tour. There is an edit button beneath your question which will enable you to do that and a {} button that enables you to format any highlighted code nicely. – PolyGeo Jun 15 '16 at 10:18
1

I have yet to find a good solution to this problem. Normally you could store the value at the class level, but I've found ArcGIS creates multiple instances of the same python class which complicates where the value actually got stored.

The solution that I've used is to create a global variable that retains the value of the previous selection.

I found setting the global variable in the updateParameters function works well. Then performing the checks for previous selected values in the updateMessages. To create a global variable you need to call it as such everytime you intend to use it (e.g. global previousProjectPath3). Make sure to clear it in your def execute code because the value will be stored and used by any other tool in your toolbox that uses it.

def updateParameters(self, parameters):

    """Modify the values and properties of parameters before internal
    validation is performed.  This method is called whenever a parameter
    has been changed."""
    if not parameters[0].value:
        global previousProjectPath3
        previousProjectPath3 = ""

def updateMessages(self, parameters):
        """Modify the messages created by internal validation for each tool
        parameter.  This method is called after internal validation."""
        if parameters[0].altered:
            path = parameters[0].valueAsText
            global previousProjectPath3
            if previousProjectPath3 != path:
                previousProjectPath3 = path

EDIT based on code provided.

import arcpy
class ToolValidator(object):
    def __init__(self):         
       """Setup arcpy and the list of tool parameters."""
       self.params = arcpy.GetParameterInfo()

    def initializeParameters(self):

        """Refine the properties of a tool's parameters.  This method is
        called when the tool is opened."""
        return

    def updateParameters(self):
        if not params[0].value:
            """Modify the values and properties of parameters before internal
            validation is performed.  This method is called whenever a parameter
            has been changed."""
            global previousValues
            previousValues = []
            if self.params[1].value and self.params[3].value:
                self.params[4].filter.list = sorted({row[0] for row in arcpy.da.SearchCursor(self.params[1].value, self.params[3].value.value) if row[0]})
            if self.params[1].value and self.params[3].value:
                self.params[5].filter.list = sorted({row[0] for row in arcpy.da.SearchCursor(self.params[1].value, self.params[3].value.value) if row[0]})        

    def updateMessages(self):
        """Modify the messages created by internal validation for each tool
        parameter.  This method is called after internal validation."""
        if self.params[4].altered:
            selectedValue = self.params[4].value
            global previousValues
            if selectedValue in previousValues:
                self.params[4].setWarningMessage("Already selected")
            else:
                previousValues.append(selectedValue)
  • thanks a lot for your generous reply and your help...but unfortunately when I have tried to adjust my validation code according to your suggestion, there was an error, moreover I can not understand the idea of your solution, can you please explain what means setting the global variable setting the global variable? – N.G Jun 18 '16 at 21:06
  • 1
    If you edit your response to show what code you have now, I could make give you a better answer and code example. – dslamb Jun 20 '16 at 15:37
  • I have put the code as an answer because it is longer than to be written in a comment...waiting for your generous reply....I have tried in this code to execute your suggestion but it does not work – N.G Jun 22 '16 at 17:07
  • any suggestion for the filtering parameter values through the validation code? – N.G Jun 25 '16 at 6:18
  • Could you also include what kinds of parameters you have. My params[0] was specific to the tool I was creating, so from the code you provided it doesn't seem that is what you check if it has been altered. You might also want previousProjectPath3 to be a list to store previous selected values. I will try and edit my response. – dslamb Jun 27 '16 at 13:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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