Hi. I want to create a script tool that let's the user select one or more Line ID and set a definition query and I want to choose from a list based on the Line ID field in the feature class (SetParameter?). How can I do that? Not sure if I need to append to a list and if an expression can grow or shrink depending on how many values are selected.
e.g. LineID = '0001' OR LineID = '0002'..................................
Here is the simple (single value) version:
import arcpy Line_ID = arcpy.GetParameterAsText(0) mxd = arcpy.mapping.MapDocument("Current") df = arcpy.mapping.ListDataFrames(mxd, "*")[0] layer = arcpy.mapping.ListLayers(mxd, "Lines")[0] sc = set(r[0] for r in arcpy.da.SearchCursor(layer, "LID")) for s in sc: where_clause = "LID = '"+Line_ID+"'" layer.definitionQuery = where_clause ext = layer.getExtent() df.extent = ext del mxd, df, layer, sc, s
Solved! Go to Solution.
If you want to have the values in the dialog of the tool then this needs to be scripted in the tool validation. For example if you have a tool like this:
and the result is to print a where clause of the values like this:
... the code in the script would be:
import arcpy fc = arcpy.GetParameterAsText(0) fld = arcpy.GetParameterAsText(1) selvals = arcpy.GetParameterAsText(2) lst_vals = selvals.split(';') where = "{0} in ('{1}')".format(arcpy.AddFieldDelimiters(fc, fld), "','".join(lst_vals)) arcpy.AddMessage(where)
the validation code for the "updateParameters" function would be:
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[1].altered: if self.params[1]: fc = str(self.params[0].value) fld = str(self.params[1].value) lst_vals = list(set(r[0] for r in arcpy.da.SearchCursor(fc, (fld)))) self.params[2].filter.list = lst_vals return
In the validation, when the selected field is changed and has a value, the fc name and the fld name are read and used for the search cursor to create the list of unique values. This list is assigned to the filter.list of the 3rd parameter.
The parameters are defined as follows:
For the field you can filter the type of fields (optionally), but you will have to define "Obtained from" and select the feature layer.
The list of values is a Multivalue (Yes) and the filter is an empty value list.
If you want to have the values in the dialog of the tool then this needs to be scripted in the tool validation. For example if you have a tool like this:
and the result is to print a where clause of the values like this:
... the code in the script would be:
import arcpy fc = arcpy.GetParameterAsText(0) fld = arcpy.GetParameterAsText(1) selvals = arcpy.GetParameterAsText(2) lst_vals = selvals.split(';') where = "{0} in ('{1}')".format(arcpy.AddFieldDelimiters(fc, fld), "','".join(lst_vals)) arcpy.AddMessage(where)
the validation code for the "updateParameters" function would be:
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[1].altered: if self.params[1]: fc = str(self.params[0].value) fld = str(self.params[1].value) lst_vals = list(set(r[0] for r in arcpy.da.SearchCursor(fc, (fld)))) self.params[2].filter.list = lst_vals return
In the validation, when the selected field is changed and has a value, the fc name and the fld name are read and used for the search cursor to create the list of unique values. This list is assigned to the filter.list of the 3rd parameter.
The parameters are defined as follows:
For the field you can filter the type of fields (optionally), but you will have to define "Obtained from" and select the feature layer.
The list of values is a Multivalue (Yes) and the filter is an empty value list.
How do you set up the expression for the definition query?
Combing your code with my example would yield something like:
import arcpy fc = arcpy.GetParameterAsText(0) fld = arcpy.GetParameterAsText(1) lst_vals = arcpy.GetParameter(2) where = "{0} in ('{1}')".format(arcpy.AddFieldDelimiters(fc, fld), "','".join(lst_vals)) arcpy.AddMessage(where) mxd = arcpy.mapping.MapDocument("Current") df = arcpy.mapping.ListDataFrames(mxd, "*")[0] layer = arcpy.mapping.ListLayers(mxd, fc)[0] # assuming that the layer is selected from the TOC layer.definitionQuery = where ext = layer.getExtent() df.extent = ext del mxd, df, layer
If the idea is to zoom in to the selected items...
I can't seem to get the list values to appear after selecting a field (which are numbers stored as text). It tells me I have illegal list values.
Also the only way I can get a field list to appear in the UI is to use a feature class data type (feature layer = nothing). I would like to use feature layer so only layers in the data frame can be used.
Have not started on the definition query part yet.
import arcpy fc = arcpy.GetParameterAsText(0) fld = arcpy.GetParameterAsText(1) selvals = arcpy.GetParameterAsText(2) lst_vals = selvals.split(';') where = "{0} in ('{1}')".format(arcpy.AddFieldDelimiters(fc, fld), "','".join(lst_vals)) arcpy.AddMessage(where)
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[1].altered: if self.params[1].value: fc = str(self.params[0].value) fld = str(self.params[1].value) lst_vals = list(set(r[0] for r in arcpy.da.SearchCursor(fc, (fld)))) #self.params[1].filter.list = [str(field.name) for field in arcpy.Describe(fc).fields] self.params[2].filter.list = lst_vals return def updateMessages(self): """Modify the messages created by internal validation for each tool parameter. This method is called after internal validation.""" return
I can't seem to get the list values to appear after selecting a field (which are numbers stored as text). It tells me I have illegal list values.
try to change the code from lines 4 - 6 into a single line, it might solve the problem with the list.
lst_vals = arcpy.GetParameter(2)
Otherwise add a arcpy.AddMessage(lst_vals) to the code to see what the list is like.
Also the only way I can get a field list to appear in the UI is to use a feature class data type (feature layer = nothing). I would like to use feature layer so only layers in the data frame can be used.
Thanks very much Xander, got it to work. There were null values in a feature in my feature class which was causing the problems.
Any Idea how to clear the definition query from the UI so all the values show up the next time the user uses the tool? Would I put the code in initializeParameter?
Hi Amy,
The InitializeParameter method is not the place, I think, since at that point you don't know what the layer is that will be selected, and clearing all where clauses is not a good thing to do.
I think you will need to pump in some more code in the updateParameters method, where you access the layer in the TOC and clear any where clause. The other option would be to determine the source of the featurelayer and access the featureclass instead of the featurelayer, since a featureclass does not have a where clause applied to it.
Kind regards, Xander