Multiple Data Driven Frames Using Python

1671
8
08-04-2016 10:08 AM
Johnkelly4
New Contributor II

I've been trying to write a script that can do the following:

Example:
-Two frames on a layout, one on top and one on the bottom
-10 data driven pages
-It would display DDP's 1, 3, 5, 7, 9 top frame and DDP's 2, 4, 6, 8, 10 on the bottom frame, for a total of 5 sheets of paper.

Below is what I have come up with so far. The script runs them one at a time instead of together. Anyone know what I am missing?

import arcpy

import time

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

#Lists all dataframes within the mxd

df1 = arcpy.mapping.ListDataFrames(mxd,"Layers")[0]

df2 = arcpy.mapping.ListDataFrames(mxd,"Layer 02")[0]

lyr = arcpy.mapping.ListLayers(mxd, "", df2)[0]

rows = arcpy.SearchCursor(lyr,"CATEGORY = 'Even'",

                          fields="Shape; Id; CATEGORY; Name",

                          sort_fields="Id A")

for pageNum in range(1, mxd.dataDrivenPages.pageCount + 1,2): 

  mxd.dataDrivenPages.currentPageID = pageNum

  for row in rows:

    df2.extent = row.Shape.extent

    df2.scale = 2400

    arcpy.RefreshActiveView()

    time.sleep(2)

    print row.getValue("Name")

del mxd

0 Kudos
8 Replies
DarrenWiens2
MVP Honored Contributor

This seems to work using a modern cursor. This works for 'nice' data, but you may have to do some work if you're missing IDs or something.

>>> import time

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

... df1 = arcpy.mapping.ListDataFrames(mxd,"Layers1")[0]

... df2 = arcpy.mapping.ListDataFrames(mxd,"Layers2")[0]

... index = 'buff' # my DDP index layer

... features = {row[0]:row[1] for row in arcpy.da.SearchCursor(index,['ID','SHAPE@'])} # all index features

... for pageNum in range(1,mxd.dataDrivenPages.pageCount,2):

...    mxd.dataDrivenPages.currentPageID = pageNum

...    df1.extent = features[pageNum].extent

...    df2.extent = features[pageNum+1].extent

...    arcpy.RefreshActiveView

...    time.sleep(2)

Johnkelly4
New Contributor II

Thank you sir! Your version seemed to work (and was much cleaner). What exactly did you mean by 'nice' data and missing IDs? What kinds of problems do you see with this?

0 Kudos
DarrenWiens2
MVP Honored Contributor

It just doesn't actually read the available IDs. It assumes that every ID exists between 1 and the length of the list. If you happened to have IDs 1, 2, 3, 5 (missing 4), when the loop is on 3 it will look for value 4 (pageNum+1), but since it's not there, there will be an error. If all your IDs exist, there should be no problem.

Johnkelly4
New Contributor II

Ah ok, I think I will be fine in that case. Will I be able to call on different field information with this? For example: I have a field called scale that determines the scale for each extent (1:2,400, 1:3,600, etc). So could something like this work:

import time 

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

df1 = arcpy.mapping.ListDataFrames(mxd,"Layers")[0] 

df2 = arcpy.mapping.ListDataFrames(mxd,"Layer02")[0]

fc = "D:\Practice\Arcpy\New_Shapefile.shp"

index = fc # my DDP index layer

features = {row[0]:row[1] for row in arcpy.da.SearchCursor

            (index,['ID','SHAPE@','Scale'])} # all index features 

for pageNum in range(1,mxd.dataDrivenPages.pageCount,2): 

    mxd.dataDrivenPages.currentPageID = pageNum 

    df1.extent = features[pageNum].extent

    df1.scale = Scale

    df2.extent = features[pageNum+1].extent

    df2.scale = Scale

    arcpy.RefreshActiveView

    print ['ID']

    arcpy.mapping.ExportToPDF(mxd, r"D:\Practice\Arcpy\Page_" + str(pageNum) + ".pdf")

    time.sleep(2)

del mxd

0 Kudos
DarrenWiens2
MVP Honored Contributor

You would need to add the scale value into the features dictionary. Before, the dictionary had the form: {ID1:SHAPE1, ID2:SHAPE2,...}. Below, I've changed it to be like: {ID1:[SHAPE1,SCALE1], ID2:[SHAPE2,SCALE2]...}. So, later on, you can reference by ID (features[pageNum]) and get either the shape ([0]), or scale ([1]).

import time   

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

df1 = arcpy.mapping.ListDataFrames(mxd,"Layers")[0]   

df2 = arcpy.mapping.ListDataFrames(mxd,"Layer02")[0

fc = "D:\Practice\Arcpy\New_Shapefile.shp" 

index = fc # my DDP index layer 

 

features = {row[0]:[row[1],row[2]] for row in arcpy.da.SearchCursor 

            (index,['ID','SHAPE@','Scale'])} # all index features   

for pageNum in range(1,mxd.dataDrivenPages.pageCount,2😞   

    mxd.dataDrivenPages.currentPageID = pageNum   

    df1.extent = features[pageNum][0].extent 

    df1.scale = features[pageNum][1]

    df2.extent = features[pageNum+1][0].extent 

    df2.scale = features[pageNum+1][1]

    arcpy.RefreshActiveView 

    print ['ID'

    arcpy.mapping.ExportToPDF(mxd, r"D:\Practice\Arcpy\Page_" + str(pageNum) + ".pdf"

    time.sleep(2

del mxd

Johnkelly4
New Contributor II

Thank you! It worked out great! Sorry I am new to arcpy. So just to make sure I understand what happened -

The dictionary part is this?: features = {row[0]:[row[1],row[2]]...       (row[0] is attached to 'ID' and row[1] to 'Scale'?)

This part specifies what goes in each row? (index,['ID','SHAPE@','Scale'])} # all index features

0 Kudos
DarrenWiens2
MVP Honored Contributor

Yes, this is the line that builds the dictionary. It uses some shorthand called a dictionary comprehension:

features = {row[0]:[row[1],row[2]] for row in arcpy.da.SearchCursor(index,['ID','SHAPE@','Scale'])}

This line is equivalent to:

features = {}

with arcpy.da.SearchCursor(index,['ID','SHAPE@','Scale']) as cursor:

    for row in rows:

        features[row[0]] = [row[1],row[2]] # I think this is right, but may get key error, I can't remember

And, yes, you're mostly right about which part specifies what in row. The first value ('ID') becomes the first item in row (row[0]), second value ('SHAPE@') goes into row[1], and third value ('Scale') goes into row[2]. If you listed more fields, they would go into row[3], row[4], etc.

Johnkelly4
New Contributor II

Got it! Thanks again for all your help!!

0 Kudos