Automating a Find and Zoom Process

9122
21
07-01-2014 07:20 AM
ib
by
New Contributor II
Hi all,
I am a total newbie to programming anything into Arc with little to no programming experience but I'm finding the need to be able to automate certain processes so now's as good of time as any to start learning.  The problem is, I need to get this process going ASAP, of course...

What I'm trying to do seems fairly simple:

I have a bunch of points with unique ID's and I need to be able to export the area around these points from my base map to JPG's at multiple zoom levels.

My process might look like this:
1. Enter the unique ID into a field
2. The program/script would zoom to the point with this ID and export a JPG at two or three different scales.

Can I do this in model builder or will I need to write a Python script? 
Thanks!
0 Kudos
21 Replies
IanMurray
Frequent Contributor
This would probably be a python script, and from your description, you'd probably want to make a script tool, so you have an interface where you enter the ID field you want, and probably define your output name and location for the pdfs.

You can do everything you want in regards to zooming to the the selected ID using the arcpy.mapping module. 

I have a script similar to what you need if you need a good starting point to work from, though when you say little to no programming knowledge, how little is that?  The script I had need to zoom to a polygon that was added to my template map then zoom out a selected amount from that initial zoom and then export it to a pdf, while changing a few text elements in the map along the way(probably not what you need, other than the zooming to and setting scale.)
ib
by
New Contributor II
I built simple websites by hand about 15 years ago, writing all of the HTML code myself- so, real simple stuff compared to Python/true programming but I think some of the same principles apply.  If I saw your script, I could least figure out how to remove the portions that I didn't need, and maybe modify them to work how I want.  I need to learn the tools for sure, and what Arc "wants" in order to run a successful script.  It sounds like in your script, instead of zooming to the polygon, I'd replace that with the ID from my metadata, for starters.

So I would add a new toolbox and then add a script into it? (headslap- I know... noob!)  I tried that yesterday with random scripts and didn't quite know what the scripts did, but at least I was able to get them to start...

Would you mind posting the script here please, and I can try to import it into Arc?  Thanks for the response!  🙂
0 Kudos
IanMurray
Frequent Contributor
To make a script tool, go to the toolbox you want in the catalog, and select add(not new, though you would think new would make sense right?), then script.  I cut down my script a bunch, trying to make it closer to what you need.  I'd do some reading up on script tools, tool parameters, so you can create your tool. 

#Importing Modules
import arcpy 


#Declaring Variables
ID = arcpy.GetParameterAsText(0)
OutputLocation = arcpy.GetParameterAsText(1)

#Assembling Map - Selecting MXD, Dataframe, and Selecting Layer by Attribute
#Creating a Map Document Object within python, referencing the .mxd you want to work with.
mxd = arcpy.mapping.MapDocument(r"put filepath to your map here")

#Once you have a map document object in python, you can access its various elements, now we need to access the dataframe the layer you are using is in.
#The line of code below makes a list of all the dataframes in the map document object we made.  The [0] returns the first dataframe in our map document, 
#if you need to access additional dataframes, you would use a different index, we now have made a dataframe object in python and can access the layers in it
df = arcpy.mapping.ListDataFrames(mxd,"*")[0]

#Now to Create a Layer Object, the line of code below returns a list of all the layers in the dataframe, with this name.  The [0] returns the first layer with that name instead of the whole list
Layer = arcpy.mapping.ListLayers(mxd, "Your Layer Name here", df)[0]

#Selecting by Attribute, Zooming to Feature, and Setting Scale
#This line performs a select by attribute on our Layer object, using a new selection, with an SQL query of ID = the ID variable we created using getparameterAsText(0)
arcpy.SelectLayerByAttribute_management(Layer, "NEW_SELECTION" , "ID = " + ID)


scales = [scale 1 here , scale 2 here, scale 3 here]
for scale in scales:
  #Selecting by Attribute, Zooming to Feature, and Setting Scale
  #This line performs a select by attribute on our Layer object, using a new selection, with an SQL query of ID = the ID variable we created using getparameterAsText(0)
  arcpy.SelectLayerByAttribute_management(Layer, "NEW_SELECTION" , "ID = " + ID)
  #This zooms the dataframe to the selected feature
  df.zoomToSelectedFeatures()
  df.scale = scale

  #Clearing selected features so they do not show up selected on map
  arcpy.SelectLayerByAttribute_management(Layer, "CLEAR_SELECTION")

  #Exporting map dataframe view to pdf, I have it set up to save
  arcpy.mapping.ExportToPDF(mxd, OutputLocation + ID + scale + ".pdf", "Page_Layout", 640, 480)

#Cleaning out memory by deleting the python objects
del mxd; del df, del Layer


When you make the script tool, you will need to define a few input parameters, for the ID number you want and for the Output folder where you want the file, you might want one for the file name as well.  THe arcpy.GetParameterAsText takes input from the tool to be used in the script. 

Edit: Ah heck, I went ahead and make the tool for ya, you will need to edit a few lines in the code, but otherwise should be good
Edit Edit: Add the last line from the code on this thread to your script tool, by right clicking on it and selecting edit on the script tool
ib
by
New Contributor II

Ian, I appreciate what you've done for me so far but I'm still very lost. 

I've tried reading the Arc help pages, plugging in parameters, running the script in Python and in Arc (and sometimes crashing it!) but I'm just not quite getting it.

Basically all I believe that is working properly is the mxd file path.  I've been able to set the parameters to return a list of layers so I can select the one where my points/table is located that I want to search but I don't know how to set up the script or the parameters to be able to search it.

Attached is a lame test file I made with random Lat/Long coordinates and other columns.  I'd be trying to search for numbers in the "ID" column to zoom to and print out.

Do I need to change the .py file for every ID that I want to search for?  That's what the SQL field is for in the parameters GUI, right?  Ugh.  So frustrating - it just hasn't clicked yet.  Any more help please?

0 Kudos
IanMurray
Frequent Contributor

I apologize about the first script tool I loaded, I forgot to save the script I was working on as a .py, I left it as a .txt, so it couldn't be editted from the catalog.


From your last response you seem to want to iterate over all the ID fields in a layer, and then export PDFs of each of those IDs at 3 pre-defined zooms.

I fixed my script tool, and made it take 7 parameters, that way you don't need to modify the script at all(unless you want to change how they name when they export, I've made the script export with the mxd name, then ID Number, then the Scale Number, so they are all differnt names on export.  Currently the tool, will let you export them by ID one at a time, but if you need to iterate all ID's in a Layer and export them all at the same scale, then the script could be changed to do them all at once, and should be faster that way.

I've tested this script tool this time(was in a bit of a rush last time), so it should be out of the box useable, just unzip, navigate to the toolbox in ArcCatalog, open the tool, fill in the parameters and let it run.  To fill in the Output Location, you can either navigate to it from the tool, or click and drag it to the input, same for the MXD parameter.  For the Layer Name, make sure you copy the name exactly as it shows up in the table of contents in your map document.

Hope this does what you need, if you want it editted to do all ID's in a Layer, it should be a fairly easy adjustment.

Edit: To run the tool as is, it took my 5 year old computer about 42 seconds, hopefully yours goes a bit quicker.

0 Kudos
ib
by
New Contributor II

When I unzip the "Toolbox2" file, I get a "Toolbox2.tbx" and that's it.  Putting it into Arc, there's no script file in the toolbox.  Posting the Python code up here will work- I can add it to a toolbox as a script like I did the previous one.  Sorry to be a pain! 

*edit* Yes, I'd like to just input one ID at a time for now.  I may want to be able to enter multiple ID's in the future but never all of them at the same time.  Thanks!

0 Kudos
IanMurray
Frequent Contributor


Hello Again,

I just unzipped a new copy of the toolbox, and the script was in there(see attached)

I can go ahead and post my code, and I'll put a screenshot of how the parameters were set up as well if you want.  When you open the tbx in ArcCataog it should show a script which you can double clcik and run(incidentally, what version of ArcGIS are you running?  That can effect toolboxes).


#Importing Modules
import arcpy 


#Declaring Variables
ID = arcpy.GetParameterAsText(0)
OutputLocation = arcpy.GetParameterAsText(1)


#Assembling Map - Selecting MXD, Dataframe, and Selecting Layer by Attribute
#Creating a Map Document Object within python, referencing the .mxd you want to work with.
mxdpath = arcpy.GetParameterAsText(2)
mxd = arcpy.mapping.MapDocument(mxdpath)
#Once you have a map document object in python, you can access its various elements, now we need to access the dataframe the layer you are using is in.
#The line of code below makes a list of all the dataframes in the map document object we made.  The [0] returns the first dataframe in our map document, 
#if you need to access additional dataframes, you would use a different index, we now have made a dataframe object in python and can access the layers in it
df = arcpy.mapping.ListDataFrames(mxd,"*")[0]
#Now to Create a Layer Object, the line of code below returns a list of all the layers in the dataframe, with this name.  The [0] returns the first layer with that name instead of the whole list
LayerName = arcpy.GetParameterAsText(3)
Layer = arcpy.mapping.ListLayers(mxd, LayerName, df)[0]


#Selecting by Attribute, Zooming to Feature, and Setting Scale
#This line performs a select by attribute on our Layer object, using a new selection, with an SQL query of ID = the ID variable we created using getparameterAsText(0)
arcpy.SelectLayerByAttribute_management(Layer, "NEW_SELECTION" , "ID = " + ID)
scale1 = arcpy.GetParameterAsText(4)
scale2 = arcpy.GetParameterAsText(5)
scale3 = arcpy.GetParameterAsText(6)


scales = [scale1, scale2, scale3]
for scale in scales:
  #Selecting by Attribute, Zooming to Feature, and Setting Scale
  #This line performs a select by attribute on our Layer object, using a new selection, with an SQL query of ID = the ID variable we created using getparameterAsText(0)
  arcpy.SelectLayerByAttribute_management(Layer, "NEW_SELECTION" , "ID = " + ID)
  #This zooms the dataframe to the selected feature
  df.zoomToSelectedFeatures()
  df.scale = scale
  #Clearing selected features so they do not show up selected on map
  arcpy.SelectLayerByAttribute_management(Layer, "CLEAR_SELECTION")
  mxdname = mxd.filePath.split("\\")[-1]
  mxdname = mxdname.replace(".mxd" , "")
  #Exporing map dataframe view to pdf, I have it set up to save
  arcpy.mapping.ExportToPDF(mxd, OutputLocation + "/" + mxdname + "ID_" + ID + scale + ".pdf", "Page_Layout", 640, 480)

I sent a new copy of the toolbox, the two images, and the actual python script file, so you don't have to copy the code posted.

ib
by
New Contributor II

I am using Arc 10.1.

Getting closer.... I had to convert the x,y data to a Shapefile so that there were Object ID's and it's happy about that now.  I don't want to use the OID field to select the point though, I want to use the Target "ID" field in the excel file.  I am getting the following error now:

Executing: Zoomto %1% "Z:\Bulldog\Junk\Script Test1" Z:\Bulldog\BaseMaps\ArcScriptTest.mxd ArcTests_01 10000 5000 1000

Start Time: Thu Jul 10 10:30:45 2014

Running script Zoomto...

<type 'exceptions.IndexError'>: list index out of range

Failed to execute (Zoomto).

Failed at Thu Jul 10 10:30:47 2014 (Elapsed Time: 2.00 seconds)

I'm not sure which is out of range (zoom levels don't seem to make a difference).  I've tried to enter in my ID number in multiple ways, TAR101 or just 101 or %TAR101%, %101%, etc....

Is there any reason why you chose to type in the layer name vs. having a pull-down list (Parameters: Layer)?

Do any of the Parameter Property values need to be changed?  I see how to make the Scales to a list with Filter:Value List. That could come in handy later...

0 Kudos
ib
by
New Contributor II

Oh wait, "List index out of range" must mean there's something wrong with my layer name... maybe?  I only have one data frame so that shouldn't be the "list" issue.  Thinking aloud here...

*edit*  Nope.... lol.  New layer name didn't help.

0 Kudos