4

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()
8
  • Questions: How are you obtaining the DataFrame object? On the Source tab, is the "Run Python script in process" box checked?
    – blah238
    Apr 13, 2012 at 17:13
  • @blah238 df = arcpy.mapping.ListDataFrames(mxd, "Layers")[0]; Run Python script in process IS checked.
    – Roy
    Apr 13, 2012 at 17:21
  • And mxd? Are you getting that from arcpy.mapping.MapDocument("CURRENT") like @MC5's example?
    – blah238
    Apr 13, 2012 at 17:32
  • @blah238 I've used both the arcpy.mapping.MapDocument("CURRENT") and the arcpy.mapping.MapDocument(r'pathName') methods with the same result.
    – Roy
    Apr 13, 2012 at 17:39
  • A derived parameter will not be added, it must be an output parameter
    – user681
    Apr 13, 2012 at 17:47

3 Answers 3

4

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?

3
  • What I'm after is the use of a Feature Layer, that is to say it only needs to persist for the length of the script. In the Python window, as soon as the line arcpy.MakeFeatureClass(arg1, arg2) is reached, that layer is added to the display. This is not the case in a script tool. Does that make it more clear -- this tool has about 250 different potential inputs, and they don't need to persist past zooming to the feature and clipping a wetlands layer.
    – Roy
    Apr 13, 2012 at 14:58
  • I referenced a shapefile path only as a convenience for this example to create the 'addLayer' feature layer to pass to AddLayer(). Any other way that you have a feature layer in hand should work the same way in the AddLayer() method. Maybe should is the crux of your problem, it just doesn't...
    – MC5
    Apr 13, 2012 at 15:06
  • I'm still a bit confused by your solution. I've stored the MakeFeatureClass call as a variable and passed it to AddLayer with no luck. I'm not sure that AddLayer is even necessary because it works in the Python window without AddLayer. I have a feeling there is some problem with the script tool properties (updated post to include properties window!)
    – Roy
    Apr 13, 2012 at 15:49
1

It sounds like you can use arcpy.mapping.AddLayer(dataFrame, addLayer), as described by MC5, but you don't want something persisting on disk? Would it be an issue if you just set up a scratch geodatabase that your script just cleans out at the start of your script and repopulates with the result every time the script runs?

1
  • The reason I opted for a feature layer is because you can run a SelectLayerByAttributes(inLayer, SelectionType, whereClause) followed by zoomToSelectedFeatures(). This technique is not available to .lyr files, only feature layers.
    – Roy
    Apr 16, 2012 at 14:00
0

Roy, a question for you. Are these Python (arcpy) scripts being run from within the ArcMap session or outside? If outside - you can use arcpy.mapping.AddLayer.

1
  • 1
    The desired result is to have the script run from a script tool within an ArcMap custom Toolbox (in ArcMap). In either case, wouldn't the mapping.AddLayer command still be available within an arcmap session?
    – Roy
    Apr 13, 2012 at 11:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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