Select to view content in your preferred language

Definition query multiple values

5536
7
Jump to solution
12-17-2014 05:22 PM
AmyKlug
Frequent Contributor

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
1 Solution

Accepted Solutions
XanderBakker
Esri Esteemed Contributor

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:

FieldValuesInList01.png

and the result is to print a where clause of the values like this:

FieldValuesInList02.png

... 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:

FieldValuesInList03.png

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.

View solution in original post

0 Kudos
7 Replies
XanderBakker
Esri Esteemed Contributor

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:

FieldValuesInList01.png

and the result is to print a where clause of the values like this:

FieldValuesInList02.png

... 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:

FieldValuesInList03.png

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.

0 Kudos
AmyKlug
Frequent Contributor

How do you set up the expression for the definition query?

0 Kudos
XanderBakker
Esri Esteemed Contributor

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...

0 Kudos
AmyKlug
Frequent Contributor

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
0 Kudos
XanderBakker
Esri Esteemed Contributor

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.

  • In the parameter definition of the tool you have to define that the field is obtained from the featurelayer:

parameterdef.png

  • A feature layer type still let's you browse for a featureclass that is not in your TOC, so this is a possible source for errors
0 Kudos
AmyKlug
Frequent Contributor

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?

0 Kudos
XanderBakker
Esri Esteemed Contributor

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

0 Kudos