Push list of field names from validator into script tool

3355
14
Jump to solution
02-19-2019 01:04 AM
Nicole_Ueberschär
Esri Regular Contributor

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. 

0 Kudos
14 Replies
Nicole_Ueberschär
Esri Regular Contributor

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?

0 Kudos
RandyBurton
MVP Alum

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.

0 Kudos
Nicole_Ueberschär
Esri Regular Contributor

Strange... For me both don't do anything. 

0 Kudos
RandyBurton
MVP Alum

And to confirm, you replaced the validator code with the appropriate section from above and then refreshed the tool?

0 Kudos
Nicole_Ueberschär
Esri Regular Contributor

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‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos