The script below imports a spreadsheet into ArcMap and generates a shapefile. Currently, I can use the ArcMap tool that interfaces with the script to navigate to the spreadsheet I want to import. This tool will be used periodically to import from several spreadsheets, and I'd like to have the tool interface be just a dropdown, where each item links to a corresponding spreadsheet. Is this possible?

# Author: John K. Tran
# Contact: jtran20@masonlive.gmu.edu

import arcpy
import os
from os import listdir
import csv
print "arcpy imported"

Input CSV can look like:

Lat,Lon,First Name,Last Name

Make sure 'Lat' and 'Lon' fields are the 1st and 2nd column in the CSV 


incsv = arcpy.GetParameterAsText(0) 
#Change this to the path of your CSV file.

outfc = r'N:\ReferenceMaterials\ArcGIS Python\Pavement Cores by County\A 
Interim Shapefiles' + '\\' + arcpy.GetParameterAsText(1) + '.shp' 
#Change this to the path of your output FC.

spatialref = arcpy.SpatialReference(4326) 
#Create the spatial reference object as WGS84. Can modify if desired.

testData = r'N:\ReferenceMaterials\ArcGIS Python\Pavement Cores by County\A     
Interim Shapefiles'
if len(os.listdir(testData)) == 0:
    for t in listdir(testData):
        if t.endswith('.shp'):
            arcpy.Delete_management(os.path.join(testData, t))

os.path.basename(outfc), "POINT", None, None, None, spatialref)

csv.register_dialect("xls", delimiter=",", lineterminator="\n") 
#Register the dialect for native CSV syntax in Microsoft Excel.
f = open(incsv, "r")
reader = csv.reader(f, dialect = "xls")

headers = reader.next() #Read the first line as the header names.

for header in headers[2:]: 
#Add fields for remaining columns if needed. Default is TEXT field.
    arcpy.AddField_management(outfc, header, "TEXT")

cursor = arcpy.da.InsertCursor(outfc, ['SHAPE@XY'] + headers[2:]) 
#Create InsertCursor.
count = 0
for row in reader:
    if count % 1000 == 0:
        print "processing row {0}".format(count)
    Ycoord = row[0] # Make sure 'Lat' is in the 1st column.
    Xcoord = row[1] # Make sure 'Lon' is in the 2nd column.
    newrow = [(float(Xcoord), float(Ycoord))] + row[2:]
    cursor.insertRow(newrow) # Insert point in FC for each row in CSV.
    count += 1

del cursor

Yes, you can do this using a script tool validator. You would also need to configure the parameter (in the tool's properties) to 'Value List' for its 'Filter' property.

See the documentation at: Customizing script tool behavior

As the doco says,

Validation is everything that happens before a tool's OK button is clicked.

This can include populating the list of items in a drop-down.

There are some examples of code on the linked page.

The only odd part of how all this works (in my opinion) is that the Python validator class is NOT part of your script tool's script itself, but instead it is a separate Python script that is stored within the script properties. In the script properties, click on the 'Validation' tab, and then the 'Edit' button to edit the script. NB: You should configure ArcMap to use your preferred Python IDE as the editor, otherwise you'll be stuck editing your script in Notepad, or some other plain text editor.

Below is an example of how it could look for your particular case. Note that this is simply the default Validator script with only two lines added - the excelDir global variable at the top, and the prameter filter list assignment in initializeParameters().

import arcpy, os

excelDir = "C:/path/to/ExcelFiles"

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."""
    self.params[0].filter.list = sorted([os.path.join(excelDir, filename) for filename in os.listdir(excelDir) if file.endswith(".xlsx") or file.endswith(".xls")])

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

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.