Using ModelBuilder, I want to create a tool that will let a user choose the value or values that will be used to extract a shapefile.
I have a parcel layer with a "Parcel_Type" field. I want the user to be able to choose the type of parcel to extract. So if the user wants to extract the parcels with a type "EL" then he would only have to enter "EL" as a variable. If he wants type "EL" and "CDD" he needs to enter them as multi-variables. That would be the only human interaction with the model.
So how can i use those variables in my model?
Answer
This type of operation almost always involves writing a WHERE Clause so I think using at least a little bit of Python is in order.
Also while this is possible to do with ModelBuilder, IMO, creating a Python script tool with custom validation and more control over parameter settings could provide a better user experience -- for example, by making the Field and MultiValue* parameters drop-down menus that you can pick values from instead of having to type them in.
*possibly, actually not sure about MultiValue parameters
However, since that is a more advanced exercise for another topic, I'll stick to the ModelBuilder approach, using Python only to create the WHERE clause:
- Create a new model
- Create variables (right-click the empty canvas and click Add Variable) for the input Feature Layer, Field, and MultiValue parameters.
- Right-click each of these and select Model Parameter
- Add a Calculate Value (Data Management) tool to the canvas. Connect the 3 variables to it as preconditions (just for show in this case, but it can make a difference in execution order in other situations).
Double-click the Calculate Value tool to set it up:
5a. Copy/paste the following into the Expression box (adjust to match your variable names):
buildWhereClauseMultiValue(r"%Feature Layer%","%Field%","%Values%")
5b. Copy/paste the following into the Code Block box:
import arcpy
def buildWhereClauseMultiValue(table, field, values):
"""Takes a semicolon-delimited list of values and constructs a SQL WHERE
clause to select those values within a given field and table."""
# Add DBMS-specific field delimiters
fieldDelimited = arcpy.AddFieldDelimiters(arcpy.Describe(table).path, field)
# Split multivalue at semicolons and strip quotes
valueList = [value[1:-1] if (value.startswith("'") and value.endswith("'")) else value for value in values.split(';')]
# Determine field type
fieldType = arcpy.ListFields(table, field)[0].type
# Add single-quotes for string field values
if str(fieldType) == 'String':
valueList = ["'%s'" % value for value in valueList]
# Format WHERE clause in the form of an IN statement
whereClause = "%s IN(%s)" % (fieldDelimited, ', '.join(valueList))
return whereClause5c. Set the output data type to be a SQL Expression.
5d. Click Ok and right click the output variable from the Calculate Value tool and rename it to something more descriptive like "WHERE Clause".
- Add a Select Layer By Attribute (Data Management) tool to the canvas. Connect the Feature Layer and WHERE Clause variables to the Select Layer By Attribute tool.
Add a Copy Features (Data Management) tool to the canvas. Connect the output of the Select Layer By Attribute tool to the Copy Features tool. Right click the Output Feature Class variable and check the Model Parameter and (optionally) the Add to Display options.
At this point it should look something like this:
Under the Model -> Model Properties menu give it a good name and label and save and close it.
Double-click the model in ArcToolbox to bring up the model dialog. Enter your parameters and click OK. It should export the selected features to a new feature class and add it to the map (if you checked "Add to Display" on the output feature class).
NOTES:
You can always hardcode values and not "parameterize" variables you don't want the user changing like the feature layer or field parameters. I just like having tools that are generic/reusable so I made those model parameters. In fact what I would do is simply drag and drop the generic model into a new model and then set your predefined parameters -- that way you can make several different predefined "wrapper" models, but only have one underlying model doing the work, so if you need to change its functionality, you only have to change it in one place.
If you're lucky like I was you won't have to validate the model and supply some dummy data only to remove it after validation (note how all the model elements are blank/white, meaning they're not "ready to run" -- but I was able to run it anyways upon filling out the parameters on the model dialog).
No comments:
Post a Comment