I am trying to create a value table parameter in my python toolbox where the user selects a feature class (first column) and then the second column displays a list of the fields available to choose from based on that feature class. It sounds like that was going to be available in 10.2 but the documentation doesn't mention it.
Duncan... other examples, albeit static
/blogs/dan_patterson/2016/05/19/toolbox-creation-in-arcgis-pro
I've not had the opportunity to do any scripting in ArcPro, so it is a nice surprise that this interface is now supported. I think a lot of ArcPro developers will like this.
Hi everyone. I have always said better late than never, and thought it was worthwhile to update this thread as there are some familiar faces still active on geonet....
This enhancement has been complete in ArcGIS Pro 2.4 alpha software, for both standard tbx toolboxes as well as PYT toolboxes, so you can expect to see this working when the 2.4 final release is available (or if you sign up and participate in the beta program).
How it works .... you can define a value table parameter, much like discussed above, where one column is a feature layer, and a second column is a field. If this parameter has NO DEPENDENCY set, it will apply an intrinsic dependency between the field column and the layer/data column, to read and populate the field list from the data selected in the first column. Again this only works if the parameter doesn't have a dependency set on another parameter -- we want this dependency to be applied WITHIN the value table, not between the value table parameter and another tool parameter.
I hope it makes sense. Attached a small video of the script tool properties and the tool dialog to help illustrate.
Typically when code only works with hard coded values it is because the code either does not interpret the users choice in the same way as the hard coded values, or the user has the freedom to choose options that are not anticipated and handled by the code. Where would you insert the hard coded values? Anyway, I have no time for the forums anymore outside of my weekends, so I cannot do anything until then.
Sorry for the crappy code sample!
<SPAN class="keyword token">def</SPAN> <SPAN class="token function">updateParameters</SPAN><SPAN class="punctuation token">(</SPAN>self<SPAN class="punctuation token">,</SPAN> parameters<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN> <SPAN class="string token">"""Modify the values and properties of parameters before internal validation is performed. This method is called whenever a parameter has been changed."""</SPAN> <SPAN class="comment token"># update zone features\rasters and their field names dynamically in window</SPAN> <SPAN class="keyword token">if</SPAN> <SPAN class="operator token">not</SPAN> parameters<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">.</SPAN>hasBeenValidated <SPAN class="operator token">and</SPAN> parameters<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">.</SPAN>value<SPAN class="punctuation token">:</SPAN> listOfFields <SPAN class="operator token">=</SPAN> <SPAN class="punctuation token">[</SPAN><SPAN class="punctuation token">]</SPAN> fields <SPAN class="operator token">=</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>Describe<SPAN class="punctuation token">(</SPAN>parameters<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">.</SPAN>value<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">.</SPAN>fields <SPAN class="keyword token">for</SPAN> field <SPAN class="keyword token">in</SPAN> fields<SPAN class="punctuation token">:</SPAN> listOfFields<SPAN class="punctuation token">.</SPAN>append<SPAN class="punctuation token">(</SPAN>field<SPAN class="punctuation token">.</SPAN>aliasName<SPAN class="punctuation token">)</SPAN> parameters<SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">.</SPAN>filter<SPAN class="punctuation token">.</SPAN>list <SPAN class="operator token">=</SPAN> listOfFields <SPAN class="comment token">#parameters[1].filter.list = [f.name for f in arcpy.Describe(parameters[0].value).fields]</SPAN> <SPAN class="comment token">#parameters[1].filter.list = [f.name for f in arcpy.ListFields(parameters[0].value)]</SPAN> <SPAN class="keyword token">if</SPAN> <SPAN class="operator token">not</SPAN> parameters<SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">.</SPAN>hasBeenValidated <SPAN class="operator token">and</SPAN> parameters<SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">.</SPAN>value<SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">global</SPAN> vtab <SPAN class="comment token">#vtab = arcpy.ValueTable(len(parameters[2].columns))</SPAN> vtab <SPAN class="operator token">=</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>ValueTable<SPAN class="punctuation token">(</SPAN><SPAN class="number token">2</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">if</SPAN> <SPAN class="punctuation token">(</SPAN>parameters<SPAN class="punctuation token">[</SPAN><SPAN class="number token">2</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">.</SPAN>valueAsText <SPAN class="operator token">not</SPAN> <SPAN class="keyword token">in</SPAN> <SPAN class="punctuation token">(</SPAN><SPAN class="string token">''</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">' '</SPAN><SPAN class="punctuation token">,</SPAN> None<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN> vtab<SPAN class="punctuation token">.</SPAN>loadFromString<SPAN class="punctuation token">(</SPAN>parameters<SPAN class="punctuation token">[</SPAN><SPAN class="number token">2</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">.</SPAN>valueAsText<SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">else</SPAN><SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">pass</SPAN> vtab<SPAN class="punctuation token">.</SPAN>addRow<SPAN class="punctuation token">(</SPAN><SPAN class="string token">'{0} {1}'</SPAN><SPAN class="punctuation token">.</SPAN>format<SPAN class="punctuation token">(</SPAN>str<SPAN class="punctuation token">(</SPAN>parameters<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">.</SPAN>value<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">,</SPAN> parameters<SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">.</SPAN>value<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
Looking for some help.... I have used the code above to add the full file path to a file along with an attribute name to a value table (2 columns). I have been running into issues with the code example above when the feature class contains field aliases. I saw the commented out code section for developing a field list with field name aliases and implemented that. The code accepts the feature class, recognizes the appropriate field names to choose from (including the alias named field), but throws a runtime error (99999999) when it attempts to add the row to the value table. Hard coding the file and field works. Without the ability to debug python toolboxes, I am not sure what is happening..Any insights?
def updateParameters(self, parameters): """Modify the values and properties of parameters before internal validation is performed. This method is called whenever a parameter has been changed.""" # update zone features\rasters and their field names dynamically in window if not parameters[0].hasBeenValidated and parameters[0].value: listOfFields = [] fields = arcpy.Describe(parameters[0].value).fields for field in fields: listOfFields.append(field.aliasName) parameters[1].filter.list = listOfFields #parameters[1].filter.list = [f.name for f in arcpy.Describe(parameters[0].value).fields] #parameters[1].filter.list = [f.name for f in arcpy.ListFields(parameters[0].value)] if not parameters[1].hasBeenValidated and parameters[1].value: global vtab #vtab = arcpy.ValueTable(len(parameters[2].columns)) vtab = arcpy.ValueTable(2) if (parameters[2].valueAsText not in ('', ' ', None)): vtab.loadFromString(parameters[2].valueAsText) else: pass vtab.addRow('{0} {1}'.format(str(parameters[0].value), parameters[1].value))<SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
ArcGIS 10.3 does have it. The syntax that works in a 10.3 python toolbox is as follows:
def getParameterInfo(self): """Define parameter definitions""" # First parameter param0 = arcpy.Parameter( displayName="Input Primary Table", name="in_prim_table", datatype="DETable", parameterType="Required", direction="Input") #... # Third parameter param2 = arcpy.Parameter( displayName="Primary Case Field", name="case_fields", datatype="GPValueTable", parameterType="Required", direction="Input") param2.columns = [['GPString', 'Primary Case Fields'], ['GPString', 'Secondary Case Fields']] param2.filters[0].type="ValueList" param2.filters[0].list = ["X"] # dummy list value to be replaced when user updates other parameters. param2.filters[1].type="ValueList" param2.filters[1].list=["x"] # dummy list value to be replaced when user updates other parameters. #... def updateParameters(self, parameters): """Modify the values and properties of parameters before internal validation is performed. This method is called whenever a parameter has been changed.""" if parameters[0].value and parameters[0].altered: # Return primary table tbl = parameters[0].value desc = arcpy.Describe(tbl) fields = desc.fields l=[] for f in fields: if f.type in ["String", "Text", "Short", "Long", "Float", "Single", "Double", "Integer","OID", "GUID"]: l.append(f.name) parameters[2].filters[0].list = l # first column list is updated to show field names associated with parameter 0. if parameters[1].value and parameters[1].altered: # Return secondary table tbl = parameters[1].value desc = arcpy.Describe(tbl) fields = desc.fields l=[] for f in fields: if f.type in ["String", "Text", "Short", "Long", "Float", "Single", "Double", "Integer","OID", "GUID"]: l.append(f.name) parameters[2].filters[1].list = l # second column list is updated to show field name associate with parameter1 return #...
Alexander,
I have been trying to find out how to create a drop down in a value table control, I had posted what I had achieved so far on GIS SE here then discovered this thread on this forum. You say this is not functionality available yet. I guess 10.3 does not have it too?
I have switched to a .pyt because it is much easier to deal with validation in one complete script, and all of the functionality of the script toolbox is still available within a python toolbox
I'm kind of with Dan. Outside of being able to use new functionality like value tables and the isLicensed property, the pyt approach still has left me unimpressed -- it seems like an awful lot of work for not a lot of gain.
We have logged the following enhancement request for this issue:
ENH-000083940 - Allow parameter dependencies between columns in a value table parameter in a python toolbox.
Ahhh I presume that you are referring to this type of value table
The closest are the links to working with multivalue inputs
and the in memory version of the ValueTable defined in arcpy, So I suppose it depends upon balancing the differences between the
custom and Python toolboxes
The learning curve for non-programmers is certainly faster with the former.
So you may be stuck unless you want to partition your existing structure into 2 parts... a data preparation tool where you replicate your additional sampling layers for a finite number of input layers, then selecting the desired field from the next combo which would show the fields for that layer much like
Additional layer 1
..........................
Field for layer 1
.........................etc etc
Addition layer N
.........................
Field for layer N
where the Field for layer ? are derived parameters for the appropriate field.
so if you don't want to partition your Sampling zones selection process as a separate tool as a prior step to your analysis, then you are pretty well stuck since adding more rows to the table may not be possible for a large number of additional layers.
It would also be useful for the documentation to indicate which arcpy functions/methods/properties are only supported by *.pyt toolboxes. It would certainly help minimizing the overkill I have seen where *.pyt's are used when a *.tbx would be more than adequate
Good luck
Dan I'm not sure that this is possible in the original toolbox becaue a value table data type is not available in the script toolbox. I have switched to a .pyt because it is much easier to deal with validation in one complete script, and all of the functionality of the script toolbox is still available within a python toolbox. Please see the highlighted portion of my image below for what I am trying to achieve. Let me know if you still think thats possible in a .tbx.
Alexander... wow... that is a really ugly substitute for the conventional toolbox approach...this is remniscent of the old Dialog Designer for ArcView 3.x I wonder why they have taken this approach. It will be fun going old-school again
Hi Christina Heimburg,
As we discussed in our phone conversation, this functionality is not yet possible with value tables. The code snippet that we used was the following as a workaround:
import arcpy class Toolbox(object): def __init__(self): """Define the toolbox (the name of the toolbox is the name of the .pyt file).""" self.label = "Toolbox" self.alias = "Toolbox" # List of tool classes associated with this toolbox self.tools = [Tool] class Tool(object): def __init__(self): """Define the tool (tool name is the name of the class).""" self.label = "Tool with Value Table" self.description = "Contains a model that you would like" self.canRunInBackground = False def getParameterInfo(self): """Define parameter definitions""" in_features = arcpy.Parameter( displayName= "Input Feature Class", name="in_features", datatype="GPFeatureLayer", parameterType="Optional", direction="Input") Fields = arcpy.Parameter( displayName= "Field", name="Fields", datatype="GPString", parameterType="Optional", direction="Input") value_table = arcpy.Parameter( displayName = "Selected records", name = "value_table", datatype = "GPValueTable", parameterType = "Optional", direction="Input") value_table.columns =([["GPString", "Feature Class"], ["GPString","Field"]]) params = [in_features, Fields, value_table] return params def isLicensed(self): """Set whether tool is licensed to execute.""" return True def updateParameters(self, parameters): """Modify the values and properties of parameters before internal validation is performed. This method is called whenever a parameter has been changed.""" if not parameters[0].hasBeenValidated and parameters[0].value: #listOfFields = [] #fields = arcpy.Describe(parameters[0].value).fields #for field in fields: # listOfFields.append(field.aliasName) parameters[1].filter.list = [f.name for f in arcpy.Describe(parameters[0].value).fields] if not parameters[1].hasBeenValidated and parameters[1].value: vtab = arcpy.ValueTable(len(parameters[2].columns)) if (parameters[2].valueAsText not in ('', ' ', None)): vtab.loadFromString(parameters[2].valueAsText) vtab.addRow('{0} {1}'.format(str(parameters[0].value), parameters[1].value)) parameters[2].value = vtab.exportToString() parameters[1].value = "" parameters[0].value = "" parameters[1].filter.list = [] return def updateMessages(self, parameters): """Modify the messages created by internal validation for each tool parameter. This method is called after internal validation.""" return def execute(self, parameters, messages): """The source code of the tool.""" return
this can be done with a regular toolbox using the "derived from" parameter where the featureclass is a parameter and field names are derived from it...I am surprised that the newer toolboxes dont have them. is there a reason for you to use them rather than the simpler incarnation?
Les membres connectés peuvent publier, suivre les mises à jour, et plus encore. Nouveau ici ? Inscrivez-vous gratuitement.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.