[GIS] Add feature layer to display with in a script tool for desktop mapping ‘App’

arcgis-10.0arcmaparcpypython

The point of this question is to find a way to programatically change the map extent based on user input. My method involves creating a Feature Layer & Selection, but if you have another (different) solution that gives the desired result, I'd love to hear it!

Now that I'm comfortable with arcpy and I've become aquainted with the mapping module I saw a niche. I can write start-to-finish desktop mapping applications to accomplish a specific task. This enables anyone in our office to run the 'app' without needing several years of using ArcMap to accomplish a repeatable task for a different area of interest (ie. zip-code, tax-parcel, county, etc.)

I've written a few of these scripts and associated each of them with their own MXD to give the user a GUI. When they input some sort of attribute value (watershed number, land-parcel number, county, etc.) the script makes a feature layer of that polygon and uses the zoom to selected feature method to change the extent.

The problem I'm having once I've finished debugging the 'app' through ArcMap's Python Window I create a script tool that gives the user an input box to enter in the required arguments for the program to run.

For whatever reason, ArcMap defaults to NOT adding the feature layer to the map when it reaches the line of code where it is created. Therefore, my script cannot use the zoom to selected feature method to change the extent. The rest of the script runs along just fine, but the zoom extent is still at the state level as opposed to a sub-watershed level.

Code excerpt:

try: # Clip wetlands layer to extent of user dictated parcel, calculate staticstics
    newWetland = outWetlands + "HUC_" + userHucID # variable that stores clipped wetland output location & name
    arcpy.MakeFeatureLayer_management(sheds, "currentShed", clipClause) # Create feature layer of HUC (from user input)
    arcpy.SelectLayerByAttribute_management("currentShed", "NEW_SELECTION", clipClause) # Select current HUC
    df.zoomToSelectedFeatures() # Zoom to extent of selected HUC
    arcpy.RefreshActiveView()   # Refresh view of mxd before exporting to PNG

    arcpy.Clip_analysis(wetlands, "currentShed", newWetland) # Clip dissolved wetlands layer to current HUC
    arcpy.ApplySymbologyFromLayer_management(newWetland, layers + "WetlandSymbology.lyr") # Apply wetlands symbology
    print "Finished creating wetland file for HUC #: " + userHucID + "."
except:
    print arcpy.GetMessages()
finally: # delete the feature layer if it exists if an error is present or not
    if arcpy.Exists("currentShed"):
        arcpy.Delete_management("currentShed")

Script run in the Python Window of ArcMap:
Script run correctly in Python window
SAME script run as Script-tool in custom toolbox:
Same script run through Script tool in ArcMap
Script tool Properties window:
This was suggested to me by an ESRI rep — add a feature layer as a derived, output parameter, then use the SetParameter(index, featureLayer) to get the desired layer added to display.

The parameter is derived (it isn't given by the user, but is derived by one of the user inputs), and set to output in an attempt to add it to the map.

enter image description here

Attempted Fixes:

  • ArcMap Toolbar -> Geoprocessing -> Geoprocessing Options -> 'Add results of geoprocessing operations to the display'
  • Add Feature Layer output parameter in script tool properties paired with arcpy.SetParameterAsText method
  • arcpy.mapping.AddLayer(df, layerPath)
  • df.extent = layer.getExtent()

Best Answer

Let me paraphrase the problem to see if I get it - ArcPy.Mapping.AddLayer() will add a layer to the data frame if the script is run from the python window, but not if it is run from a script tool? If that is correct, I tried to reproduce your problem as follows:

I created a script tool that takes a single arg, a 'layer alias' like 'counties'. The script then uses that alias to get a path to a shapefile, and adds it as a layer to the current doc:

# get parameters
layer_alias = arcpy.GetParameterAsText(0)
layer_path = ""

if layer_alias == "counties":
    layer_path = "C:/pathto/data/" + layer_alias + ".shp" #"C:/pathto/data/counties.shp"

# do work
mxd = arcpy.mapping.MapDocument("CURRENT")
dataFrame = arcpy.mapping.ListDataFrames(mxd, "*")[0] 
addLayer = arcpy.mapping.Layer(layer_path)
arcpy.mapping.AddLayer(dataFrame, addLayer)

And this works. Am I doing anything different than you?