Index Out of Range Error

458
4
11-18-2022 08:26 AM
ScottShenberger
New Contributor III

I have a python script that creates a map series, and I am getting an index out of range error. when I did a check on the elements, the graphic element in question is not showing in the list (see below). The elements are labeled correctly in the mxd and they are populated with data. I am not sure why the element name is not showing when I do the element checker or how to update it.

ScottShenberger_0-1668788536683.png

 

0 Kudos
4 Replies
DanPatterson
MVP Esteemed Contributor

The code portion would be useful to determine what you are querying and what checks you have put in place


... sort of retired...
0 Kudos
ScottShenberger
New Contributor III

# Create objects for the layout elements that will be moving, e.g., notes and abandonment elements
notes = arcpy.mapping.ListLayoutElements(mxd, "GRAPHIC_ELEMENT", "NOTES")[0]
abandonments = arcpy.mapping.ListLayoutElements(mxd, "GRAPHIC_ELEMENT", "ABANDONMENTS")[0]
triangle = arcpy.mapping.ListLayoutElements(mxd, "GRAPHIC_ELEMENT", "TRIANGLE")[0]
diamond = arcpy.mapping.ListLayoutElements(mxd, "GRAPHIC_ELEMENT", "DIAMOND")[0]
noteTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", "noteTitle")[0]
abandonmentTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", "abandonmentTitle")[0]

---

# Set position of notes element to place it on the page layout
triangle.elementPositionX = 19.5
triangle.elementPositionY = 12.3
noteTitle.elementPositionX = 19.8
noteTitle.elementPositionY = 12.3
notes.elementPositionX = 19.5
notes.elementPositionY = 12.2
Position = notes.elementPositionY - notes.elementHeight
# Set position of abandonments element to place it on the page layout
abandonments.elementPositionX = 19.5
abandonments.elementPositionY = Position - 0.5
diamond.elementPositionX = 19.5
diamond.elementPositionY = abandonments.elementPositionY + 0.1
abandonmentTitle.elementPositionX = 19.8
abandonmentTitle.elementPositionY = abandonments.elementPositionY + 0.1

0 Kudos
JoshuaBixby
MVP Esteemed Contributor

Instead of adding code as a comment, I suggest you update the original question with the added code.  Doing so would put all the relevant information in the same spot.  Also, don't use screenshots of code, but paste the code and use Posting code with Syntax Highlighting on GeoNet 

0 Kudos
Scott_Shenberger
New Contributor
# ---------------------------------------------------------------------------
# valvemapwinsets.py
# Created on: 04-04-2012
# Updated on: 01-16/2015 by Bill Burris
# Written by: Bill Burris
# Updated by: Scott Shenberger 05/18/2022
# Usage: Create a pdf map set containing detail inset maps and keynotes
#
# ---------------------------------------------------------------------------

import arcpy, os, sys

# Get the data driven pages object from your mxd
# You will use this to export your pages
arcpy.env.workspace = "S:\GIS_Data\VMDBValveMapsFileGDB\VMDBValveMaps\Project"
mxd = arcpy.mapping.MapDocument(r"S:\GIS_Data\VMDBValveMapsFileGDB\VMDBValveMaps\Project\MultiProcess\VMPrintingRun1.mxd")
ddp = mxd.dataDrivenPages

# Get the layer you are using as an Index Layer
# In this case the layer is in the data frame "Layers" and called "TWGridRun1"
# To create this layer, perform a select by location in the corresponding mxd on VMIndex that contains any water asset
# divide the total number of valve maps by three and round up to the nearest whole number. Select that number of records, in order
# (sort MAPID ascending).
# from this selection set on each corresponding mxd and export to the appropriate shapefile. For example, if there are
# 1761 records, each "run" script will have a corresponding TWGridRun## shapefile with 587 records. Overwrite the existing
# shapefile for the corresponding mxd ie. TWGridRun1 belongs with VMPrintingRun1.mxd etc-SBS
df = arcpy.mapping.ListDataFrames(mxd, "Layers")[0]
gridLayer = arcpy.mapping.ListLayers(mxd, "TWGridRun1", df)[0]

# Get the layer for the feature class used to indicate inset map locations
# This needs to be in the same data frame as your index layer
# In this case the layer is in the data frame "Layers" and called "DetCircles2"
# First, make a layer from the feature class "DetCircles2" from the details layer
# Update the DetCircles2.shp by exporting the current details layer and overwrite the existing DetCircles2.shp
# This update can be done only on one mxd and will be picked up by the remaining mxds.-SBS

arcpy.MakeFeatureLayer_management("DetCircles2.shp", "Details_lyr")
detailCircles = "Details_lyr"

# Set the base values for the position of your first inset map
# Locations of all the inset maps will be calculated based on these values
baseXpos = 3.0
baseYpos = 12.9

# Create objects for the layout elements that will be moving, e.g., notes and abandonment elements
notes = arcpy.mapping.ListLayoutElements(mxd, "GRAPHIC_ELEMENT", "NOTES")[0]
abandonments = arcpy.mapping.ListLayoutElements(mxd, "GRAPHIC_ELEMENT", "ABANDONMENTS")[0]
triangle = arcpy.mapping.ListLayoutElements(mxd, "GRAPHIC_ELEMENT", "TRIANGLE")[0]
diamond = arcpy.mapping.ListLayoutElements(mxd, "GRAPHIC_ELEMENT", "DIAMOND")[0]
noteTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", "noteTitle")[0]
abandonmentTitle = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", "abandonmentTitle")[0]

# Iterate through the pages of your map series and export a temporary pdf for each page
# Each page will check to see if it contains details and will construct inset maps if needed

# Each page will be exported to a temp file
# Pages with inset maps will be reset after export
for pgIndex in range(1, ddp.pageCount + 1, 1):
  print ("Run1")
  # set page name to value of "MAPID" attribute in index layer
  ddp.currentPageID = pgIndex
  pageName = ddp.pageRow.getValue('MAPID')

  # Create a name for the pdf file you will create for each page
  temp_filename = r"S:\GIS_Data\VMDBValveMapsFileGDB\VMDBValveMaps\Print\ "+\
                            str(pageName) + ".pdf"

  if os.path.exists(temp_filename): # Check to see if file already exists, delete if it does
    os.remove(temp_filename)
  print ("map" + str(pageName))
  # print pgIndex is used as a reference to show what index each map belongs too.
  print (pgIndex)
  # Use dataframe as feature to select details
  # For maps with more than 12 details SE121413, SW211313
  # Use "COMPLETELY_WITHIN" to select details else use "HAVE_THEIR_CENTER_IN"
  if (pgIndex == 340):#Old Value 1028
    dfAsFeature = arcpy.Polygon(arcpy.Array([df.extent.lowerLeft, df.extent.lowerRight, df.extent.upperRight, df.extent.upperLeft]), df.spatialReference)
    arcpy.SelectLayerByLocation_management(detailCircles, "COMPLETELY_WITHIN", dfAsFeature, "", "NEW_SELECTION")
  elif (pgIndex == 520):#old value 1568
    dfAsFeature = arcpy.Polygon(arcpy.Array([df.extent.lowerLeft, df.extent.lowerRight, df.extent.upperRight, df.extent.upperLeft]), df.spatialReference)
    arcpy.SelectLayerByLocation_management(detailCircles, "COMPLETELY_WITHIN", dfAsFeature, "", "NEW_SELECTION")
  else:
    dfAsFeature = arcpy.Polygon(arcpy.Array([df.extent.lowerLeft, df.extent.lowerRight, df.extent.upperRight, df.extent.upperLeft]), df.spatialReference)
    arcpy.SelectLayerByLocation_management(detailCircles, "HAVE_THEIR_CENTER_IN", dfAsFeature, "", "NEW_SELECTION")

  # Set position of notes element to place it on the page layout
  triangle.elementPositionX = 19.5
  triangle.elementPositionY = 12.3
  noteTitle.elementPositionX = 19.8
  noteTitle.elementPositionY = 12.3
  notes.elementPositionX = 19.5
  notes.elementPositionY = 12.2
  Position = notes.elementPositionY - notes.elementHeight
  # Set position of abandonments element to place it on the page layout
  abandonments.elementPositionX = 19.5
  abandonments.elementPositionY = Position - 0.5
  diamond.elementPositionX = 19.5
  diamond.elementPositionY = abandonments.elementPositionY + 0.1
  abandonmentTitle.elementPositionX = 19.8
  abandonmentTitle.elementPositionY = abandonments.elementPositionY + 0.1

  # Get the selection count and use it to determine if the page contains inset maps
  count = int(str(arcpy.GetCount_management(detailCircles)))

  # If more than 8 inset maps are present, move legend off of page
  legend = arcpy.mapping.ListLayoutElements(mxd, "LEGEND_ELEMENT", "Legend")[0]
  if (count > 8):
    legend.elementPositionX = -6

  # If no inset maps are contained on the current page export it normally
  if (count == 0):
    ddp.exportToPDF(temp_filename, "RANGE", pgIndex, convert_markers=True) # Export current page to temporary pdf

  # If detail features are present in the current page, create all necessary inset maps before exporting
  else:
    # The following variable is used to keep track of the number of inset maps on a page
    # It is used to get the correct data frame and piece of text when updating the map
    # It is also used to calculate the position of the inset map data frame on the page
    num = 1

    #Iterate through the selected detail map features
    for row in arcpy.SearchCursor(detailCircles):

      # Get the data frame to be used for the current inset map
      df_name = "Inset" + str(num) # Construct the name of the inset data frame you want to use - "Detail1", Detail2" etc
      dataFrame = arcpy.mapping.ListDataFrames(mxd, df_name)[0]
      dataFrame.extent = row.shape.extent  # Set the extent of the inset map data frame to the extent of the detail feature

      # The following code calculates the position of the inset map data frame based on
      # the base position values and which number inset map it is on the current page
      # In this example, the inset maps are to be arranged in rows of 2
      # and 2.0 is the size of each data frame plus how much horizontal space is wanted between them.
      # 2.3 is the size of each data frame plus how much vertical space is wanted between them.
      dataFrame.elementPositionX = baseXpos - (((num-1)%2))*2.0
      dataFrame.elementPositionY = baseYpos - ((num-1)//2)*2.20

      # Get the text element to be used for the current inset map
      txt_name = "Text" + str(num)
      text = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", txt_name)[0]

	  #get the name of the detail circles from the attribute table
      # name = int(row.FID)
      name = int(row.DETAILNO)

      # Update the text below the inset map
      # In this case the detail features contain a field called "OBJECTID"
      text.text = "DETAIL " + str(name)
      num = num + 1

    # Export the page
    ddp.exportToPDF(temp_filename, "RANGE", pgIndex, convert_markers=True) # Export current page to temporary pdf

    # Clean up layout (move inset maps and graphic text elements back off page and clear text)
    num = 1
    for row in arcpy.SearchCursor(detailCircles):
      df_name = "Inset" + str(num)
      dataFrame = arcpy.mapping.ListDataFrames(mxd, df_name)[0]
      dataFrame.elementPositionY = 16
      txt_name = "Text" + str(num)
      text = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", txt_name)[0]
      text.text = " "
      num = num + 1

    # Move the legend element back onto the page layout
    legend = arcpy.mapping.ListLayoutElements(mxd, "LEGEND_ELEMENT", "Legend")[0]
    legend.elementPositionX = 0.25
    legend.elementPositionY = 1.9


del mxd
0 Kudos