# ---------------------------------------------------------------------------
# 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