[GIS] ArcPy Data Driven Pages AttributeError: PageLayoutObject: Error in executing ExportToPDF

arcgis-10.3arcpydata-driven-pages

I am trying to export a series of datadriven pages. Executing on a single page fine no issue, executing on a few pages no issue. executing on many pages serious drama. Initially i thought it might be an issue with my mxd (ESRI response) but if I execute the script on the page where it last failed (through definition query on the index) works fine.

My assumption was either memory issue or a timeout on the export to pdf function.

import arcpy, time

#Reference MXD and layers
mxd = arcpy.mapping.MapDocument(r"C:\Working\1. Project Tasks\Constraints Maps\Constraints Maps - OW.mxd")
LabelsLayer = arcpy.mapping.ListLayers(mxd, "Labels")[0]
outpath = "C:\\Constraints\\"
#arcpy.GetParameterAsText(0)

#Reference page layout elements

for elm in arcpy.mapping.ListLayoutElements(mxd):
  if elm.name == "horzLine": horzLine = elm
  if elm.name == "Lot_Cell": Lot_Cell = elm
  if elm.name == "Landholder_Cell": Landholder_Cell = elm
  if elm.name == "ATW_Cell": ATW_Cell = elm
  if elm.name == "Ass_Start_Cell": Ass_Start_Cell = elm
  if elm.name == "Ass_End_Cell": Ass_End_Cell = elm
  if elm.name == "Ass_Laar_Cell": Ass_Laar_Cell = elm
  if elm.name == "Con_Start_Cell": Con_Start_Cell = elm
  if elm.name == "Con_End_Cell": Con_End_Cell = elm
  if elm.name == "Con_Laar_Cell": Con_Laar_Cell = elm
  if elm.name == "Notes_Cell": Notes_Cell = elm
  if elm.name == "MPC_LOGO": MPC_LOGO = elm
  if elm.name == "Header": Header = elm
  if elm.name == "Margin_Text": Margin_Text = elm
  if elm.name == "Data_Frame": Data_Frame = elm
  if elm.name == "vertLines": vertLines = elm

#Reference DDP object
ddp = mxd.dataDrivenPages
ddp.refresh()

#Graphic table variable values
maxtableHeight = 6.6
mintableHeight = 0.9
tableWidth = 41.2
upperY = 0.4
horzLineX = 0.4
Lot_CellX = 0.4001
Landholder_CellX = 2.5001
ATW_CellX = 7.0001
Ass_Start_CellX = 12.0001
Ass_End_CellX = 13.3001
Ass_Laar_CellX = 14.6001
Con_Start_CellX = 17.5001
Con_End_CellX = 18.8001
Con_Laar_CellX = 20.1001
Notes_CellX = 23.0001

#Loop through each DDP page
for pageNum in range(1, mxd.dataDrivenPages.pageCount + 1):
  mxd.dataDrivenPages.currentPageID = pageNum

  #Build selection set
  Outfolder = ddp.pageRow.Region
  PackageName = ddp.pageRow.Page_Name
  numRecords = int(arcpy.GetCount_management(LabelsLayer).getOutput(0))
  print str(PackageName) + " Number of Properties: " + str(numRecords)

  #if number of rows exceeds page space, resize row height
  if numRecords > 20:
    rowHeight = maxtableHeight / numRecords
    Data_Frame.elementHeight = 22.0
    Margin_Text.elementHeight = 6.6
    vertLines.elementHeight = 6
    MPC_LOGO.elementPositionY = 7.3
    Header.elementPositionY = 6.7
  else:
    rowHeight = 0.3
    Data_Frame.elementHeight = (28.3 - (numRecords * 0.3))
    Margin_Text.elementHeight = (12.6 - (numRecords * 0.3))
    vertLines.elementHeight = (numRecords * 0.3)
    MPC_LOGO.elementPositionY = (1 + (numRecords * 0.3))
    Header.elementPositionY = (0.4 + (numRecords * 0.3))

  #Set and clone horizontal line work
  horzLine.elementWidth = tableWidth
  horzLine.elementPositionX = horzLineX
  horzLine.elementPositionY = upperY

  y=upperY
  for horz in range(1, numRecords+1):
    y = y + rowHeight
    temp_horz = horzLine.clone("_clone")
    temp_horz.elementPositionY = y

  #Set and clone cell text elements
  rows = arcpy.SearchCursor(LabelsLayer)

  horzLine.fontSize = rowHeight / 0.043
  Lot_Cell.fontSize = rowHeight / 0.043
  Landholder_Cell.fontSize = rowHeight / 0.043
  ATW_Cell.fontSize = rowHeight / 0.043
  Ass_Start_Cell.fontSize = rowHeight / 0.043
  Ass_End_Cell.fontSize = rowHeight / 0.043
  Ass_Laar_Cell.fontSize = rowHeight / 0.043
  Con_Start_Cell.fontSize = rowHeight / 0.043
  Con_End_Cell.fontSize = rowHeight / 0.043
  Con_Laar_Cell.fontSize = rowHeight / 0.043
  Notes_Cell.fontSize = rowHeight / 0.043

  y=upperY
  for row in rows:
    if numRecords > 0:
      col1CellTxt = Lot_Cell.clone("_clone")
      col1CellTxt.text = row.getValue(unicode("Constrained_Access.LOT_PLAN"))
      col1CellTxt.elementPositionX = Lot_CellX
      col1CellTxt.elementPositionY = y

      col2 = row.getValue(unicode("LAARs.Landholder"))
      if col2 is None:
        col2text = " "
      elif col2 == "":
        col2text = " "
      else:
        col2text = row.getValue(unicode("LAARs.Landholder"))
      col2CellTxt = Landholder_Cell.clone("_clone")
      col2CellTxt.text = col2text
      col2CellTxt.elementPositionX = Landholder_CellX
      col2CellTxt.elementPositionY = y

      col3 = row.getValue(unicode("LAARs.ATW"))
      if col3 is None:
        col3text = " "
      elif col3 == "":
        col3text = " "
      else:
        col3text = row.getValue(unicode("LAARs.ATW"))
      col3CellTxt = ATW_Cell.clone("_clone")
      col3CellTxt.text = col3text
      col3CellTxt.elementPositionX = ATW_CellX
      col3CellTxt.elementPositionY = y

      col4 = row.getValue(unicode("LAARs.Approved_Assessment_Start"))
      if col4 is None:
        col4text = " "
      elif col4 == "":
        col4text = " "
      else:
        col4text = row.getValue(unicode("LAARs.Approved_Assessment_Start"))
      col4CellTxt = Ass_Start_Cell.clone("_clone")
      col4CellTxt.text = col4text
      col4CellTxt.elementPositionX = Ass_Start_CellX
      col4CellTxt.elementPositionY = y

      col5 = row.getValue(unicode("LAARs.Approved_Assessment_Finish"))
      if col5 is None:
        col5text = " "
      elif col5 == "":
        col5text = " "
      else:
        col5text = row.getValue(unicode("LAARs.Approved_Assessment_Finish"))
      col5CellTxt = Ass_End_Cell.clone("_clone")
      col5CellTxt.text = col5text
      col5CellTxt.elementPositionX = Ass_End_CellX
      col5CellTxt.elementPositionY = y

      col6 = row.getValue(unicode("LAARs.Assessment_LAARs_reference_Number"))
      if col6 is None:
        col6text = " "
      elif col6 == "":
        col6text = " "
      else:
        col6text = row.getValue(unicode("LAARs.Assessment_LAARs_reference_Number"))
      col6CellTxt = Ass_Laar_Cell.clone("_clone")
      col6CellTxt.text = col6text
      col6CellTxt.elementPositionX = Ass_Laar_CellX
      col6CellTxt.elementPositionY = y

      col7 = row.getValue(unicode("LAARs.Approved_Construction_Start"))
      if col7 is None:
        col7text = " "
      elif col7 == "":
        col7text = " "
      else:
        col7text = row.getValue(unicode("LAARs.Approved_Construction_Start"))
      col7CellTxt = Con_Start_Cell.clone("_clone")
      col7CellTxt.text = col7text
      col7CellTxt.elementPositionX = Con_Start_CellX
      col7CellTxt.elementPositionY = y

      col8 = row.getValue(unicode("LAARs.Approved_Construction_Finish"))
      if col8 is None:
        col8text = " "
      elif col8 == "":
        col8text = " "
      else:
        col8text = row.getValue(unicode("LAARs.Approved_Construction_Finish"))
      col8CellTxt = Con_End_Cell.clone("_clone")
      col8CellTxt.text = col8text
      col8CellTxt.elementPositionX = Con_End_CellX
      col8CellTxt.elementPositionY = y 

      col9 = row.getValue(unicode("LAARs.Construction_LAAR_reference_number"))
      if col9 is None:
        col9text = " "
      elif col9 == "":
        col9text = " "
      else:
        col9text = row.getValue(unicode("LAARs.Construction_LAAR_reference_number"))
      col9CellTxt = Con_Laar_Cell.clone("_clone")
      col9CellTxt.text = col9text
      col9CellTxt.elementPositionX = Con_Laar_CellX
      col9CellTxt.elementPositionY = y

      col10 = row.getValue(unicode("LAARs.Land_Access_Notes"))
      if col10 is None:
        col10text = " "
      elif col10 == "":
        col10text = " "
      else:
        col10text = row.getValue(unicode("LAARs.Land_Access_Notes"))
      col10CellTxt = Notes_Cell.clone("_clone")
      col10CellTxt.text = col10text
      col10CellTxt.elementPositionX = Notes_CellX
      col10CellTxt.elementPositionY = y
      y = y + rowHeight

  #Export to PDF
  ddp.refresh()
  outputloc = str(outpath) + str(Outfolder) + "\\" + str(PackageName) + " Constraints Maps.pdf"
  print "Exporting page:  " + outputloc
  time.sleep(1)
  arcpy.mapping.ExportToPDF(mxd, outputloc, image_quality="BETTER", jpeg_compression_quality=75,)
  print "Export Complete"

  #Clean-up before next page

  for elm in arcpy.mapping.ListLayoutElements(mxd, "GRAPHIC_ELEMENT", "*clone*"):
    elm.delete()
  for elm in arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", "*clone*"):
    elm.delete()
  del Outfolder
  del outputloc
  del y
  del PackageName
  del rows
  if numRecords > 0:
    del col2
    del col3
    del col4
    del col5
    del col6
    del col7
    del col8
    del col9
    del col10
    del col2text
    del col3text
    del col4text
    del col5text
    del col6text
    del col7text
    del col8text
    del col9text
    del col10text
    del col1CellTxt
    del col2CellTxt
    del col3CellTxt
    del col4CellTxt
    del col5CellTxt
    del col6CellTxt
    del col7CellTxt
    del col8CellTxt
    del col9CellTxt
    del col10CellTxt
  del numRecords
  time.sleep(1)
del outpath
del LabelsLayer
del mxd

The error I keep getting is:

Traceback (most recent call last):
  File "C:\Working\1. Project Tasks\Constraints Maps\Constraints Map - OW.py", line 224, in <module>
    arcpy.mapping.ExportToPDF(mxd, outputloc, image_quality="BETTER", jpeg_compression_quality=75,)
  File "C:\Program Files (x86)\ArcGIS\Desktop10.3\ArcPy\arcpy\utils.py", line 182, in fn_
    return fn(*args, **kw)
  File "C:\Program Files (x86)\ArcGIS\Desktop10.3\ArcPy\arcpy\mapping.py", line 1156, in ExportToPDF
    layout.exportToPDF(*args)
AttributeError: PageLayoutObject: Error in executing ExportToPDF

Best Answer

I ran in to a memory leak type issue which I resolved with the code snippet below, but then ran into the "layout.exportToPDF(*args) AttributeError: PageLayoutObject: Error in executing ExportToPDF" error, and have not yet resolved it. Here's how I got around the memory leak (reload the map doc every 100 reports):

TotalPages = (ReportMXD.dataDrivenPages.pageCount + 1) 
print "Total number of reports to be generated: " + str(TotalPages)
for pageNum in range(1, TotalPages):
    if (pageNum % 100 == 0):
        print "Reopening map document to free up memory..."
        del ReportMXD
        ReportMXD = arcpy.mapping.MapDocument(ReportName)        
    ReportMXD.dataDrivenPages.currentPageID = pageNum
    Destination = "c:\\temp\\reports\\results\\" + "LotID_" + str(ReportMXD.dataDrivenPages.pageRow.getValue("LegalLots.LegalLotsTemp_ID_LOT"))+ "_ServiceUtilitiesReport.pdf"
    print "Page " + str(pageNum) + " => " + Destination
    arcpy.mapping.ExportToPDF(ReportMXD, Destination, jpeg_compression_quality='10')
    print "Done saving report..."
del ReportMXD