Select to view content in your preferred language

Pass input fields to field selection, and script within Validator

2251
7
04-25-2011 08:51 AM
CameronWallace
Deactivated User
What I'm trying to do is take an input feature class, take one of it's columns (as selected by the user) and "copy" it into a new column with a specific schema (string, 20ch length), add various columns, populate them with values entered in the tool GUI, and then append the resulting table to an existing table.

I've gotten everything working except the passing of the field list from the input feature class to the field selection tool.

I suspect that this is something I should be doing in the validation script. But I also need to know that my various parameters are correct, and I need to be able to pass the value to my script properly... (field selection value that is)

This is the validation script:

class ToolValidator:
  """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."""
    #import arcpy
    #self.params = arcpy.GetParameterInfo()

  def initializeParameters(self):
    """Refine the properties of a tool's parameters.  This method is
    called when the tool is opened."""
    #self.params[8].parameterDependencies = [0]
    return

  def updateParameters(self):
    """Modify the values and properties of parameters before internal
    validation is performed.  This method is called whenever a parmater
    has been changed."""
    import arcpy
    #if self.params[0].value:
    #  FC = self.params[0].value
    #  SourceIdent = arcpy.Describe(FC).fields
    #  self.params[8].value = SourceIdent
    return

  def updateMessages(self):
    """Modify the messages created by internal validation for each tool
    parameter.  This method is called after internal validation."""
    return


This is my script code, I'm specifically looking to pass the name of the selected field from [8] to the parameter "SourceIdentity" so that I can convert the value to a string and populate the new field SourceID with the value:

## SLE Script - Authored by Cameron Wallace
## Rev 0.0 - Spring 2011
##This script is intended to; convert the feature class to a table
##strip the fields from an incoming feature class, add fields to a
##specific schema, populate those fields with input values, and two
##values from the incoming feature class. It is intended as part of
##a larger workflow.
##The final step is appending this table to an existing table that
##defines part of a related set of feature classes.

import arcpy
mxd = arcpy.mapping.MapDocument("CURRENT")

# Script arguments
SLE_Parcels_selection = arcpy.GetParameterAsText(0)
if SLE_Parcels_selection == '#' or not SLE_Parcels_selection:
    SLE_Parcels_selection = "SLE_Parcels selection" # provide a default value if unspecified

ClassI = arcpy.GetParameterAsText(1)
if ClassI == '#' or not ClassI:
    ClassI = "\"A\"" # provide a default value if unspecified

ClassII = arcpy.GetParameterAsText(2)
if ClassII == '#' or not ClassII:
    ClassII = "0" # provide a default value if unspecified

ClassIII = arcpy.GetParameterAsText(3)
if ClassIII == '#' or not ClassIII:
    ClassIII = "\"a\"" # provide a default value if unspecified

SourceShortName = arcpy.GetParameterAsText(4)
if SourceShortName == '#' or not SourceShortName:
    SourceShortName = "\"SHORT\"" # provide a default value if unspecified

Date1 = arcpy.GetParameterAsText(5)
if Date1 == '#' or not Date1:
    Date1 = "time.strftime('15/03/2011')" # provide a default value if unspecified

Date2 = arcpy.GetParameterAsText(6)
if Date2 == '#' or not Date2:
    Date2 = "time.strftime('15/03/2011')" # provide a default value if unspecified

Description = arcpy.GetParameterAsText(7)
if Description == '#' or not Description:
    Description = "\"Sample Description\"" # provide a default value if unspecified

Activity_SLE_Parcels_Relate = "C:\\Current Projects\\Other Projects\\5062xx\\506287\\GIS\\ToLContamInventory.gdb\\Activity_SLE_Parcels_Relate"
TEMPTable = "C:\\Current Projects\\Other Projects\\5062xx\\506287\\GIS\\ToLContamInventory.gdb\\TEMPTable"
# Process: Copy Rows
arcpy.CopyRows_management(SLE_Parcels_selection, TEMPTable, "")

# Process: Delete Field
arcpy.DeleteField_management(TEMPTable, "FOLIO;LEGAL_TYPE;ATTRIB_VALUE;VALUE_DESC;ParcelKey;Shape_Length;Shape_Area")

SourceIdentity = arcpy.GetParameterAsText(8)

# Process: Add Field
arcpy.AddField_management(TEMPTable, "Activity_Class_I", "TEXT", "", "", "3", "", "NULLABLE", "NON_REQUIRED", "")
arcpy.AddField_management(TEMPTable, "Activity_Class_II", "LONG", "", "", "", "", "NULLABLE", "NON_REQUIRED", "")
arcpy.AddField_management(TEMPTable, "Activity_Class_III", "TEXT", "", "", "3", "", "NULLABLE", "NON_REQUIRED", "")
arcpy.AddField_management(TEMPTable, "SourceShortName", "TEXT", "", "", "15", "", "NULLABLE", "NON_REQUIRED", "")
arcpy.AddField_management(TEMPTable, "Date1", "DATE", "", "", "", "", "NULLABLE", "NON_REQUIRED", "")
arcpy.AddField_management(TEMPTable, "Date2", "DATE", "", "", "", "", "NULLABLE", "NON_REQUIRED", "")
arcpy.AddField_management(TEMPTable, "Description", "TEXT", "", "", "250", "", "NULLABLE", "NON_REQUIRED", "")
arcpy.AddField_management(TEMPTable, "SourceID", "TEXT", "", "", "20", "", "NULLABLE", "NON_REQUIRED", "")

rows = arcpy.UpdateCursor(TEMPTable)
for row in rows:
 row.Activity_Class_I = ClassI
 row.Activity_Class_II = ClassII
 row.Activity_Class_III = ClassIII
 row.SourceShortName = SourceShortName
 row.Date1 = Date1
 row.Date2 = Date2
 row.Description = Description
 row.SourceID = str(SourceIdentity)
 rows.updateRow(row)

del row
del rows

# Process: Append
arcpy.Append_management(TEMPTable, Activity_SLE_Parcels_Relate, "NO_TEST", "", "")

arcpy.Delete_management (TEMPTable)


Any help or suggestions greatly welcomed!

Thanks
Tags (2)
0 Kudos
7 Replies
LoganPugh
Frequent Contributor
The line
SourceIdent = arcpy.Describe(FC).fields
sets SourceIdent to a list of Field objects, not a string, and you can't directly convert a list of objects to a string, at least not in a way that makes sense for what you're doing.

You'll need to loop through the field objects in the field list and build a string.

e.g.
SourceIdent = ",".join(field.name for field in arcpy.Describe(FC).fields)


You can change the comma in the string just prior to .join to any delimiter you want.
0 Kudos
LoganPugh
Frequent Contributor
Actually if I understand correctly, you want parameter 8 to be a list of selectable values with each of the column names, is that right?

If so, take a look at the "To update a filter" section in the help topic Customizing Script Tool Behavior. E.g.:

self.params[8].filter.list = [str(field.name) for field in arcpy.Describe(FC).fields]


You could even take it one step further and remove any fields you know you don't want to be listed:
self.params[8].filter.list = [str(field.name) for field in arcpy.Describe(FC).fields if str(field.name) not in ('OBJECTID', 'SHAPE', 'SHAPE_Length', 'SHAPE_Area', 'BLOB')]
0 Kudos
CameronWallace
Deactivated User
Pretty much...
I got it working, thanks for your help.
Final code block for validation script:
class ToolValidator:
  """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."""
    import arcpy
    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 parmater
    has been changed."""
    if self.params[0].value:
      FC = self.params[0].value
      self.params[8].filter.list = [str(field.name) for field in arcpy.Describe(FC).fields]
    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
RaphaelR
Deactivated User
i´m trying to do something very similar, but got one problem.
in the tool i want to specify one shapefile and from its fields i want to use a some for calculations.
the user should specifiy those fields and the field selection should be limited to fields containing a certain string in their name.
this is my code for filtering the 1st field - the rest would look pretty much the same...

def updateParameters(self):
    """Modify the values and properties of parameters before internal
    validation is performed.  This method is called whenever a parmater
    has been changed."""
    infeat = str(self.params[0].value)
    
    self.params[1].filter.list = [str(field.name) for field in arcpy.Describe(infeat).fields if "DTV" in str(field.name)]
      
    return


the initialize/update parameters are both unchanged.

the filter seems to work and only displays those fields that contain "DTV" in their name -
but if i select one of the filtered fields in the tool, i get an error:
"000800 : The value is not a member of <value>." - but i´m sure the value is one of those in the list.

any ideas?
0 Kudos
RaphaelR
Deactivated User
even if i use the same tool validator code as cameron i get the "000800 : The value is not a member of [the list of fields appears here]." error. this has to be something simple but i´m running out of ideas where to look for the problem.

the first parameter is a feature layer(tried featureclass, table and shapefile too), the second a field.
0 Kudos
LoganPugh
Frequent Contributor
Change the second parameter to String, I don't think Field parameters can have filters applied to them.

Alternatively, instead of writing ToolValidator code, use a Field parameter and set its Obtained From value to the feature layer/feature class/table parameter and it will be populated automatically.
0 Kudos
RaphaelR
Deactivated User
Change the second parameter to String, I don't think Field parameters can have filters applied to them.


that did it, thanks a lot!
0 Kudos