Thursday, January 3, 2013

ArcPy 10.1 - Multiple Data Frames and Data Driven Pages

Data driven pages is a great way to automate map production over a given area, and it works right out of the box with a single data frame.  If you have 2 or more data frames though, you will need to control the movement of each data frame object by performing some sort of coding (ArcObjects or ArcPy).

A simple way to move multiple data frames is to:

  1. Get a list of all data frames
  2. Identify the parent data frame
  3. Move the extents of the other data frame
Sounds simple?  Well it is.

To get started, get a reference to the map document

mxd = arcpy.mapping.MapDocument("CURRENT")

Change "CURRENT"  to a path if not run in ArcMap.  Then list all the data frames

dfs = arcpy.mapping.ListDataFrames(mxd)

Now how do you know what data frame is the parent data frame or what data frame is a child data frame? Luckily at 10.1, the data driven page object provides a property called dataFrame, which returns the DataFrame object.  At 10.0, you would either use names or indexing values to determine which is the parent or not, but this example is for 10.1.

ddp = mxd.dataDrivePages
parentDF = ddp.dataFrame

Next step is to pan the other data frames to the extent of the parent data frame's extent.


for pageNum in range(1, ddp.pageCount + 1):

   for df in dfs:
      ddp.currentPageID = pageNum
      row = ddp.pageRow
      extent = row.Shape.extent
      if (df.name == parentDF.name) and (df.scale == parentDF.scale):
         print 'I found the parent frame'
      else:
         df.panToExtent(extent)
   arcpy.mapping.ExportToPNG(mxd, r"C:\Project\OutPut\ParcelAtlas_" + str(pageNum) + ".png")

Here we have a bunch of code that loops through each data driven page area and then modifies each underlying data frame that isn't the parent.  After the data frames are changes, the code then exports the maps to PNG to the '...\output' folder with reference to the page number.

Enjoy

4 comments:

Naeim Dastgir said...

Hi Andrew,

This is a very interesting post and I could get it to work as a script with no problem.

Here's a question: is it possible to manage two frames with different extents using Arcpy and DDP? i.e. I have two data frames each with their own DDp settings. is it possible to switch between the DDPs using Arcpy?

Thanks
Naeim

Andrew said...

The way you want to do it, no you cannot do it that way. It's one DDP per document.

You can manually change each dataframe using arcpy though. Check out the dataframe object in the help document.

Greg Dunnigan said...

Hi Andrew, this is a really useful post for me so thank you very much. I'm pretty new to Python, but I was able to make this work.

I was only able to get this to work using a shapfile though. My question is how would this work with a joined layer?

For example, in a shapfile, the 'extent' value above is 'row.Shape.extent' with 'Shape' being extent in question.

But in the layer I'm working with, I have a layer file where the Shape field is called '..Shape'. If I to plug that whole thing in, I get an error that it can't find the first part.

Worst case scenario, I can always just use a shapefile, but was wondering if there was something you could suggest.

thanks
Greg

Andrew said...

You can try using the arcpy.Describe() on the joined layer and get the shape field name. Then using that, you might be able to use the getValue() on the DDP's row object. The row object by the way acts just like a 10.0 row object.