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

answered Apr 13, 2012 at 14:53
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. Commented 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... Commented 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!) Commented 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?

answered Apr 16, 2012 at 13:26
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. Commented 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.

answered Apr 12, 2012 at 23:12
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? Commented Apr 13, 2012 at 11:05

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.