Hi folks,
with help of https://community.esri.com/people/xander_bakker/blog/2016/07/19/implementing-cascading-drop-down-lis... I gained some understanding how I can make my script tool take conditions and additional information to fill the tool.
I have three input parameters (a directory, a min and a max value). I would like to have a multiple choice list of those indicators in my txt file (in that directory) that are not empty.
My validator should check the first txt file in that directory, read the field names, if they are not within a list of excluded field names then read the first value, if it is not None than add the field name to a list. Works perfectly in pyscripter.
And I also get the correct list displayed in my tool script. Buuut, the tool says the parameter's field type is invalid after displaying the field names. I could imagine that it has something to do with the filter in the parameter which is set to DataType=Field but of course it is not really a field name any longer after returning it from my script. But what else could I use? Or can I somehow tell the self.params that it is still a (list of) field name(s)?
This is my updateParameters.
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 filedir:
arcpy.env.workspace = filedir
list_of_files = arcpy.ListFiles("*.txt")
firsttable=list_of_files[0]
print(firsttable)
print(filedir)
complete_filename = str(filedir)+"\\"+firsttable
print(complete_filename)
table=arcpy.MakeTableView_management(complete_filename, "kivu_tview")
desc = arcpy.Describe(table)
#fieldnamesoriginal=[field.name.encode("utf-8") for field in desc.fields] ##collects all fieldnames
fieldselectlist=[]
for ofields in desc.fields:
ftype=ofields.type
fname=ofields.name.encode("utf-8")
if ftype=="Double" or ftype=="Long":
print(fname)
if fname!="Profile_No" and fname!="Longitude (degrees_east)" and fname!="Latitude (degrees_north)" and fname!="Bot. Depth (m)" and fname!="Depth (m)":
with arcpy.da.SearchCursor(table, fname) as calcursor:
for calcrow in calcursor:
if calcrow[0] is not None:
fieldselectlist.append(fname)
break
print(fieldselectlist)
self.params[3].filter.list =fieldselectlist
self.params[3].value=fieldselectlist
return
Any hint would be highly appreciated.
Solved! Go to Solution.
Is there a way to enable the "Select all/unselect all" functionality for the tool?
I was able to "select all" after loading the list through the validator but the buttons inside the tool don't work. I guess that would another "on change" event but how do I catch that?
I had used the select all button the tool interface provides without a problem. I did not try the deselect button but will check it out later.
Strange... For me both don't do anything.
And to confirm, you replaced the validator code with the appropriate section from above and then refreshed the tool?
As far as I can see, yes. I added this to have all selected: self.params[3].value=self.params[1].filter.list after your line 79.
I also had to add another loop to go through all tables in the folder. It turned out (in contrast to what I thought) that not all tables have data for the same indicators... This is my updated validation code. Note, that I have params[3] in the end... Ah, yes, and I added a lower case sort of the field names.
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."""
filedir=self.params[0].value
if filedir:
arcpy.env.workspace = filedir
list_of_files = arcpy.ListFiles("*.txt")
firsttable=list_of_files[0]
for txtfile in list_of_files:
complete_filename = str(filedir)+"\\"+str(txtfile)
table=arcpy.MakeTableView_management(complete_filename, "kivu_tview")
desc = arcpy.Describe(table)
arcpy.AddMessage("Table to be analyzed: "+str(table))
fieldselectlist=[] #Will collect the field names
for ofields in desc.fields:
ftype=ofields.type
fname=ofields.name.encode("utf-8")
if ftype in ["Double","Long"]:
#print(fname)
if fname not in ["Profile_No","Longitude (degrees_east)" ,"Latitude (degrees_north)" ,"Bot. Depth (m)","Depth (m)","Depth (0.5 m )" ,"Depth (0.5 m)","Distance from platform","Time (actual)"]:
with arcpy.da.SearchCursor(table, fname) as calcursor:
for calcrow in calcursor:
if calcrow[0] is not None:
if calcrow[0] not in fieldselectlist:
fieldselectlist.append(fname)
break
arcpy.AddMessage(fieldselectlist)
arcpy.Delete_management("kivu_tview","Table View") # delete table view
#sorted_list=fieldselectlist.sort(key=str.lower)
#sorted_list=fieldselectlist.sort(key=lambda x:x.lower())
if 'pH' in fieldselectlist and 'pH corrected' in fieldselectlist:
fieldselectlist.remove('pH')
if 'Dissolved Oxygen (mg/L)' in fieldselectlist and 'Dissolved Oxygen corrected (mg/L)' in fieldselectlist:
fieldselectlist.remove('Dissolved Oxygen (mg/L)')
sorted_list_not_cs=sorted(fieldselectlist,key=str.lower)
arcpy.AddMessage("sortiert, not case sensitive: "+str(sorted_list_not_cs))
# for multiple choice
try:
if self.params[3].values: #if this parameter has seleted values
oldValues = self.params[3].values #set old values to the selected values
except Exception:
pass
self.params[3].filter.list = sorted_list_not_cs #set the filter list equal to the sorted values
newValues = self.params[3].filter.list
self.params[3].value=self.params[3].filter.list
try:
if len(oldValues): # if some values are selected
self.params[3].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
#self.params[3].filter.list=sorted(fieldselectlist)
return