2

I have created a Python script tool in ArcGIS Pro 1.4.1 which has tool validation.

The fourth parameter on my tool dialog, which is of type string with multiple values allowed, after choosing some values looks like this:

enter image description here

I would like this list of value to be sorted and contain only unique values.

I think the updateParameters function should be able to achieve that. My updateParameters function appears below.

The code has an if statement to cater for the function being called before any values have been added. Then what I think it should be doing is:

  1. Read the values from the ValueTable object of parameter 3 into a string of values separated by semi-colons
  2. Create a list of those values by splitting on semi-colons
  3. Make a unique sorted list
  4. Join that list back into a string and load that string into the value table object.

At this point I would expect my five unordered values to have become four values sorted alphabetically.

My code gives no error, but when I change the value of a parameter, triggering the updateParameters function, it leaves the list with the original five members still unordered.


def updateParameters(self):
    """Modify the values and properties of parameters before internal
    validation is performed. This method is called whenever a parameter
    has been changed."""
    if self.params[3].value is not None:
        valueString = self.params[3].value.exportToString()
        # Sort and make values unique
        valueList = valueString.split(";")
        sortedList = sorted(set(valueList))
        self.params[3].value.loadFromString(";".join(sortedList))

Can anyone see what I am missing or may be misunderstanding?

I have assumed that the string is being exported from and read by the value table using semi-colons but do not know where I can check that.


The answer by @AlexTereshenkov has all but solved this for me. The lingering issue which may or may not represent a new problem (that may need a new question) is an error that it seemed to bring in:

enter image description here

The value table appears to be updating perfectly but it is throwing ERROR 000800 and saying that one or both of the values in the picture are not in the choice list but they both are.

def updateParameters(self):
    """Modify the values and properties of parameters before internal
    validation is performed. This method is called whenever a parameter
    has been changed."""
    if self.params[3].altered:
        self.params[3].value = sorted(list(set(self.params[3].value.exportToString().split(";"))))

I suspect that I'm seeing the error when Alex is not because I have spaces in my strings when he does not. I'll experiment some more tomorrow.

3

You don't have to make a value for the parameter by loading it from a string. It's enough just to do the assignment:

def updateParameters(self):
  self.params[0].value = sorted(list(set(self.params[0].value.exportToString().split(";"))))

Parameter is of data type String. Multiple values is checked. The animation attached to see the tool in action:

enter image description here

Thanks to the validation added, the values user chooses will be sorted automatically. If a value has been chosen earlier, it won't get kept.

Update for ERROR 000800:

ArcGIS Pro handles parameter values a bit different when they contain spaces. Add the arcpy.AddMessage(msg.split(";")) into your script source code to see the values printed in Pro.

["'Msg 6-7'", "'Msg 8-9'", 'Msg1', 'Msg2']

The values with the space will be wrapped into single quote (') making them mismatching with the allowed values you enter in the filter.

Interestingly enough, it seems as one cannot have multiple values which have single quotes, such as Street O'ryan and Street O'Bryan. This results in error in Pro. Simple tool with no validation at all; just two allowed values in filter.

enter image description here

If your values contain the space(s), you could replace the single quotes symbols before updating the parameter values. This would do the trick:

values = sorted(list(set(self.params[0].value.exportToString().split(";"))))
self.params[0].value = [i[1:-1] if [i[0], i[-1]] == ["'", "'"] else i for i in values]
  • Many thanks - that solves all but an ERROR 000800 that it seemed to trigger (see update to my question). The working day just ended here so I'll try and figure where the error comes from tomorrow. – PolyGeo May 15 '17 at 7:08
  • @PolyGeo, updated my answer, the problem should be solved. – Alex Tereshenkov May 15 '17 at 8:20
  • @PolyGeo, did it go well? – Alex Tereshenkov May 16 '17 at 5:45
  • That bit worked perfectly but I have some messy additional tool validation that is not playing nicely with it. At the moment I have some other higher priority tasks to attend to before I can get back to trying to make the tool validation totally work. For the moment enough of it works for me to get a pass mark, and you an excellent. – PolyGeo May 16 '17 at 6:05

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.