AnsweredAssumed Answered

Customizing Multiple Element Layout Manager?

Question asked by ajose_lgl on Jun 16, 2020
Latest reply on Jul 6, 2020 by joseanna

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

Outcomes