Select to view content in your preferred language

Customizing Multiple Element Layout Manager?

834
3
06-16-2020 09:14 AM
by Anonymous User
Not applicable

I've been trying to customize Esri's free code sample Multiple Element Layout Manager to fit my own mapping. It rearranges page layout elements such as inset maps, north arrows and text on different map series pages all using a single map document. 

Below is the pageLayout Table with the data driven index page (Toronto 1, 2), and the data frame properties (elementPositionX, elementPositionY, elementWidth, elementHeight, XMin, YMin, XMax, YMax, rotation, scale). I always get the error message: "C:\Mytemplates\Resources\MultipleTemplates\MultipleElementLayoutManager_10.0_v1\ZoomToPage.py", line 46, in <module> arrangeDFs(pageLayoutRow, df.name) File "C:\Mytemplates\Resources\MultipleTemplates\MultipleElementLayoutManager_10.0_v1\ZoomToPage.py", line 24, in arrangeDFs df.scale = rowInfo[9] IndexError: list index out of range.

If line 24 is deleted, then it works, but I want the data frames to follow the scales in the table. The first code lays out all the map elements according to the table. The second code is used to populate the pageLayout table

import arcpy, json, os, sys, time

#Set up relative paths
relPath = os.path.dirname(sys.argv[0])

#Get input page value from GP dialog
pageName = str(arcpy.GetParameterAsText(0))

#Function that arranges data frames based on the field info within the PageLayoutElements table
def arrangeDFs(row, dfName):
  rowInfo = json.loads(row.getValue(dfName))
  df = arcpy.mapping.ListDataFrames(mxd, dfName)[0]
  df.elementPositionX = rowInfo[0]
  df.elementPositionY = rowInfo[1]
  df.elementWidth = rowInfo[2]
  df.elementHeight = rowInfo[3]
  newExtent = df.extent
  newExtent.XMin = rowInfo[4]
  newExtent.YMin = rowInfo[5]
  newExtent.XMax = rowInfo[6]
  newExtent.YMax = rowInfo[7]
  df.extent = newExtent
  df.rotation = rowInfo[8]
  df.scale = rowInfo[9]
  
############################ MAIN SCRIPT STARTS HERE ##############################

arcpy.AddMessage("Processing map: " + str(pageName))

#Reference MXD
mxd = arcpy.mapping.MapDocument("current")  #CURRENT

#Use DDP object when not resetting the page back to the default template
if pageName <> "Default Template":
  ddp = mxd.dataDrivenPages
  pageID = mxd.dataDrivenPages.getPageIDFromName(pageName)
  mxd.dataDrivenPages.currentPageID = pageID

#Reference pageLayoutTable
pageLayoutTable = arcpy.mapping.ListTableViews(mxd, "PageLayoutElements")[0]

#Move all data frames off the layout and into their default positions
pageLayoutCursor = arcpy.SearchCursor(pageLayoutTable.dataSource, "Name = 'Default Template'")
pageLayoutRow = pageLayoutCursor.next()
for df in arcpy.mapping.ListDataFrames(mxd):
  arrangeDFs(pageLayoutRow, df.name)

#Move appropriate data frames onto the layout
pageLayoutCursor = arcpy.SearchCursor(pageLayoutTable.dataSource, "Name = '" + pageName + "'")
pageLayoutRow = pageLayoutCursor.next()
for df in arcpy.mapping.ListDataFrames(mxd):
  if not pageLayoutRow.isNull(df.name):
    arrangeDFs(pageLayoutRow, df.name)

#Arrange other layout elements
nArrow1 = arcpy.mapping.ListLayoutElements(mxd, "MAPSURROUND_ELEMENT", "NorthArrow1")[0]
nArrow1.elementPositionX = json.loads(pageLayoutRow.getValue("Title_NorthArrow"))[0]
nArrow1.elementPositionY = json.loads(pageLayoutRow.getValue("Title_NorthArrow"))[1]
nArrow2 = arcpy.mapping.ListLayoutElements(mxd, "MAPSURROUND_ELEMENT", "NorthArrow2")[0]
nArrow2.elementPositionX = json.loads(pageLayoutRow.getValue("Title_NorthArrow"))[2]
nArrow2.elementPositionY = json.loads(pageLayoutRow.getValue("Title_NorthArrow"))[3]
arcpy.RefreshActiveView()
import arcpy, os, sys
relPath = os.path.dirname(sys.argv[0])

def setDF(df):
  fieldValue = "[" + \
               str(round(df.elementPositionX, 2)) + "," + str(round(df.elementPositionY, 2)) + "," + \
               str(round(df.elementWidth, 2)) +     "," + str(round(df.elementHeight, 2)) + "," + \
               str(long(df.extent.XMin)) +          "," + str(long(df.extent.YMin)) + "," + \
               str(long(df.extent.XMax)) +          "," + str(long(df.extent.YMax)) + "," + \
               str(long(df.rotation)) +             "," + str(long(df.scale)) + "]"
  return fieldValue

############################ MAIN SCRIPT STARTS HERE ##############################

#REFERENCE MXD, DDP OBJECT, AND LAYOUT ELEMENTS
mxd = arcpy.mapping.MapDocument("CURRENT")
ddp = mxd.dataDrivenPages
pageName = ddp.pageRow.getValue(ddp.pageNameField.name)
northArrow1 = arcpy.mapping.ListLayoutElements(mxd, "MAPSURROUND_ELEMENT", "NorthArrow1")[0]
northArrow2 = arcpy.mapping.ListLayoutElements(mxd, "MAPSURROUND_ELEMENT", "NorthArrow2")[0]

#REFERENCE PAGELAYOUT TABLE
pageLayoutTable = arcpy.mapping.ListTableViews(mxd, "PageLayoutElements")[0]

#UPDATE INFORMATION FROM PAGELAYOUT TABLE
pageLayoutCursor = arcpy.SearchCursor(pageLayoutTable.dataSource, "\"Name\" = '" + pageName + "'")
pageLayoutRow = pageLayoutCursor.next()

if pageLayoutRow == None:               #INSERT A NEW ROW - INSERT CURSOR
  arcpy.AddMessage("Adding New Row")
  pageInsertCursor = arcpy.InsertCursor(pageLayoutTable.dataSource)
  pageInsertRow = pageInsertCursor.newRow()
  pageInsertRow.Name = pageName

  #Set Data Frame information
  for df in arcpy.mapping.ListDataFrames(mxd):
    if df.elementPositionX > 0 and df.elementPositionX < 11:  #don't set values if DF is off the page
      pageInsertRow.setValue(df.name, setDF(df))

  #Set Locator and North Arrow
  pageInsertRow.Title_NorthArrow = "[" + str(round(northArrow1.elementPositionX,2)) + "," + str(round(northArrow1.elementPositionY,2)) + "," + \
                                   str(round(northArrow2.elementPositionX,2)) + "," + str(round(northArrow2.elementPositionY,2)) + "]"              
  
  pageInsertCursor.insertRow(pageInsertRow)
  del pageInsertCursor, pageInsertRow

else:                                   #UPDATE EXISTING ROW - UPDATE CURSOR
  arcpy.AddMessage("Updating Existing Row")
  pageUpdateCursor = arcpy.UpdateCursor(pageLayoutTable.dataSource, "\"Name\" = '" + pageName + "'")
  pageUpdateRow = pageUpdateCursor.next()

  #Set Data Frame information
  for df in arcpy.mapping.ListDataFrames(mxd):
    if df.elementPositionX > 0 and df.elementPositionX < 11:  #don't set values if DF is off the page
      pageUpdateRow.setValue(df.name, setDF(df))

  #Set Locator and North Arrow
  pageUpdateRow.Title_NorthArrow = "[" + str(round(northArrow1.elementPositionX,2)) + "," + str(round(northArrow1.elementPositionY,2)) + "," + \
                                   str(round(northArrow2.elementPositionX,2)) + "," + str(round(northArrow2.elementPositionY,2)) + "]"             
  
  pageUpdateCursor.updateRow(pageUpdateRow)
  del pageUpdateCursor, pageUpdateRow
  
del pageLayoutCursor, pageLayoutRow

I'm totally new to python, but customizing it was pretty easy, until I wanted to change both rotation and scale. Hopefully I'm just missing something simple

0 Kudos
3 Replies
JeffBarrette
Esri Regular Contributor

I don't see the issue.  In your screenshot, the scales are 5000 and 4014, correct?  They appear to be the 10th [9] field in the list.  

Jeff

0 Kudos
AnnaJose1
New Contributor

Yes 5000 and 4014 are the scales. I'm not sure why the error message appears that "line 24, in arrangeDFs df.scale = rowInfo[9] IndexError: list index out of range." 

If I delete line 24, it works just fine, but the scales won't be what I want. Or if I interchange, so that rotation is 10th and scale is 9th field, then rotation doesn't work. 

0 Kudos
christinebrooks
Occasional Contributor

Hi there! I am looking to do something similar to what you have done here (rearranging page inset maps on different map series pages all using a single map document), I am just wondering how others have gone about exporting the output though? are you exporting each page separately? or is there a script that can recognise each page set up and export it all at once? and thoughts would be really appreciated!

0 Kudos