Friday 27 December 2019

arcpy - Generating multivalue choice list in ArcGIS using Tool Validation without using Frequency?



I'm trying to adapt a model and script combination found on ESRI's blog site titled 'Generating a multivalue choice list'.


However, I've concluded that part of the validation used in the embedded script is reliant upon the 'Frequency' Tool in order to function properly, but this is only available with and Advanced license (lame). The blog post explains the workflow and where to download the models and scripts (but I'll happily post them up here upon request). As far as I can tell, the core of the functionality I'm after, generating a multivalue choice list:


enter image description here


..is predicated upon the validation script working properly. Without the validation, I'm unable to get the values from the field to appear as a list. Is there anything I can remove out of this validation script to get the functionality I'm after, or is there a workaround? I'm unfamiliar with the validation process. Here is the code for the validation (I was going to post as a Code Sample, but this looks like it might be easier to follow): enter image description here


[Editor note: here is the actual validation code, the image is not correct]


import arcpy

class ToolValidator(object):
"""Class for validating a tool's parameter values and controlling
the behavior of the tool's dialog."""


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):
"""Modify the values and properties of parameters before internal
validation is performed. This method is called whenever a parmater
has been changed."""
if self.params[1].altered: #Set condition - if the input field value changes
if self.params[1].value: #if the field parameter has a value
for field in arcpy.Describe(self.params[0].value).fields: #iterate through fields in the input dataset
if field.name.lower() == self.params[1].value.value.lower(): #find the field object with the same name as field parameter
try:
if self.params[2].values: #if this parameter has seleted values

oldValues = self.params[2].values #set old values to the selected values
except Exception:
pass
values = set() #create an empty set
fieldname = self.params[1].value.value #set the value of variable fieldname equal to the input field value
FrequencyTable = arcpy.Frequency_analysis (self.params[0].value, "in_memory\Frequency", self.params[1].value.value, "") #for large tables create a frequency table
cursor = arcpy.SearchCursor(FrequencyTable, "", "", self.params[1].value.value, "{0} A".format(self.params[1].value.value)) #open a search cursor on the frequency table
for row in cursor: #loop through each value
values.add(row.getValue(fieldname)) #add the value to the set
self.params[2].filter.list = sorted(values) #set the filter list equal to the sorted values

newValues = self.params[2].filter.list
try:
if len(oldValues): # if some values are selected
self.params[2].values = [v for v in oldValues if v in newValues] # check if seleted values in new list,
# if yes, retain the seletion.
except Exception:
pass

def updateMessages(self):
"""Modify the messages created by internal validation for each tool

parameter. This method is called after internal validation."""
return

Is it possible that my assumption (via testing) that the validation is the key piece is false, and that something else isn't allowing the values to be exposed as a selectable list? Many thanks in advance. Having this type of functionality will really jump start the adoption of several key workflows I'm trying to distribute in our company!



Answer



I thought some people might find this valuable. ESRI was gracious enough to help work through this and find an alternate to the validation used in the blog post which does not require an Advanced license. While I certainly had to figure out some additional items, I cannot take credit for the validation code. But, the ends justify the means and this qualifies as the answer to my question. Here you go:


import arcpy
class ToolValidator(object):
"""Class for validating a tool's parameter values and controlling
the behavior of the tool's dialog."""


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):
"""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[0].value and self.params[1].value:
self.params[2].filter.list = sorted({row[0] for row in arcpy.da.SearchCursor(self.params[0].value, self.params[1].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."""

return

Using the arcpy.da.SearchCursor returns values from the chosen field very fast considering the number of records its searching (at least in my data). I may start a new thread to see if anyone has any ideas on how to apply a filter to the validation based on a query. I hope this helps someone, but I'm glad we have an answer!


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...