Hi all,
I am trying to create an ArcGIS Pro python tool that prepopulates a list with field names from an imported shapefile. I want to be able to delete field names from the list, but the tool I have created won't allow it. I am guessing that I need to add some type of update part to the script, but just not sure. In the tool, a red "X" appears next to each field name, but when clicked does not actually delete the field name. Any help would be appreciated. here is the tool as it currently exists:
class FieldNames(object):
def __init__(self):
"""Define the tool (tool name is the name of the class)."""
self.label = "FieldNames"
self.description = ""
self.canRunInBackground = False
def getParameterInfo(self):
"""Define parameter definitions"""
fc = arcpy.Parameter(
displayName="fc",
name="fc",
datatype="GPFeatureLayer",
parameterType="Required",
direction="Input")
names = arcpy.Parameter(
displayName="field names",
name="fields",
datatype="GPString",
parameterType="Required",
direction="Input"
)
names.parameterDependencies = [fc.name]
names.multiValue = True
params = [fc,names]
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."""
# This comes from here https://gis.stackexchange.com/questions/330672/deriving-field-parameter-from-table-parameter-in-python-toolbox
if parameters[0].altered:
parameters[1].values = [field.name for field in arcpy.ListFields(parameters[0].valueAsText)]
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."""
# sat = parameters[0]
fc = parameters[0].valueAsText
fields = parameters[1].valueAsText
return
Solved! Go to Solution.
Yeah, Python toolboxes have some weird quirks you have to work around.
Personally, I've never gotten Parameter.altered to work. I always do the check myself by comparing the current parameter value to the previous value stored in a variable. But it doesn't work with a variable of the Tool class. Something to do with the internal conversion into C code, I guess. My workaround for this:
Create an empty class in the toolbox file. Use this class to store variables from your tool classes:
# Toolbox.pyt
class ABC():
"""This class is used to store tool variable."""
pass
class FieldNames(object):
def __init__(self):
self.label = "FieldNames"
self.description = ""
self.canRunInBackground = False
def getParameterInfo(self):
fc = arcpy.Parameter(
displayName="fc",
name="fc",
datatype="GPFeatureLayer",
parameterType="Required",
direction="Input")
names = arcpy.Parameter(
displayName="field names",
name="fields",
datatype="GPString",
parameterType="Required",
direction="Input"
)
names.multiValue = True
# set the variable. Doesn't work with self!
ABC.fc = ""
params = [fc,names]
return params
def isLicensed(self):
return True
def updateParameters(self, parameters):
# instead of Parameter.altered, do the check yourself
if ABC.fc != parameters[0].valueAsText:
ABC.fc = parameters[0].valueAsText
parameters[1].values = [field.name for field in arcpy.ListFields(ABC.fc)]
def updateMessages(self, parameters):
return
def execute(self, parameters, messages):
fc = parameters[0].valueAsText
fields = parameters[1].valueAsText
arcpy.AddMessage(f"fc: {fc}")
arcpy.AddMessage(f"fields: {fields}")
class Toolbox(object):
def __init__(self):
self.label = "test"
self.alias = "test"
self.tools = [FieldNames]
Code formatting ... the Community Version - Esri Community
will get rid of the sad faces and provide code line numbers
Thanks. I will follow the rules next time!
Yeah, Python toolboxes have some weird quirks you have to work around.
Personally, I've never gotten Parameter.altered to work. I always do the check myself by comparing the current parameter value to the previous value stored in a variable. But it doesn't work with a variable of the Tool class. Something to do with the internal conversion into C code, I guess. My workaround for this:
Create an empty class in the toolbox file. Use this class to store variables from your tool classes:
# Toolbox.pyt
class ABC():
"""This class is used to store tool variable."""
pass
class FieldNames(object):
def __init__(self):
self.label = "FieldNames"
self.description = ""
self.canRunInBackground = False
def getParameterInfo(self):
fc = arcpy.Parameter(
displayName="fc",
name="fc",
datatype="GPFeatureLayer",
parameterType="Required",
direction="Input")
names = arcpy.Parameter(
displayName="field names",
name="fields",
datatype="GPString",
parameterType="Required",
direction="Input"
)
names.multiValue = True
# set the variable. Doesn't work with self!
ABC.fc = ""
params = [fc,names]
return params
def isLicensed(self):
return True
def updateParameters(self, parameters):
# instead of Parameter.altered, do the check yourself
if ABC.fc != parameters[0].valueAsText:
ABC.fc = parameters[0].valueAsText
parameters[1].values = [field.name for field in arcpy.ListFields(ABC.fc)]
def updateMessages(self, parameters):
return
def execute(self, parameters, messages):
fc = parameters[0].valueAsText
fields = parameters[1].valueAsText
arcpy.AddMessage(f"fc: {fc}")
arcpy.AddMessage(f"fields: {fields}")
class Toolbox(object):
def __init__(self):
self.label = "test"
self.alias = "test"
self.tools = [FieldNames]
I am not sure how you figured that out, but thanks a lot. I would have never arrived at this for a solution.