[GIS] Arcpy Creating Multi-page Table/PDF with Reportlab/PyPDF2

arcpypdfreportlabtable

I am writing a scrip to batch automate hundreds of map PDF's. Along with the PDF's I generate a unique Table/reportlist for each map from the 'receptors' that fall within each boundary of the map. The amount of receptors and consequently the size of the Table/reportlist can vary from 0 receptors to hundreds. Currently I am generating the Table/receptorlist from a merged clipped receptors for each map and then using the arcpy table to table conversion

PointL = arcpy.TableToTable_conversion(listlayer, gdb, pointsellayer)

I then use 2 arcpy.searchcursors(explain why I use 2 later) to open up and read that table. I then paste the info I need in the order and structure I want onto a ReportLab Canvas.I then use PyPDF2 to merge the map and the receporlist together into one PDF.

My Problem: sometimes as I have previously stated there are hundreds of receptors to copy and write from the Table to the receptor list. What I have been able to do (seems clunky) is write to a one page then use the Show.Page() function to move to the next page using an if statement with a counter.

*skelton outline of my code below(left out all unimportant info for the question)

pointtable = gp.Searchcursor(PointL)
pointtable2 = gp.Searchcursor(PointL)
pdffn = "ReceptorList.pdf"
c = canvas.Canvas(pdffn, pagesize=landscape(legal))
c.drawString(10, 580, "ReceptorID")
loc = 565
z=0
nlist = []
for info in pointtable:
    z+=1     #counter
    recid = info.ID  #example rows
    c.drawString(30, loc, recid)
    c.drawString(other rows...)
    loc = loc-10
    nlist.append(recid)  #storing id in list
    if loc <= 10:
        c.showPage()                    #showPage() = go to next page
        print "ReceptorListpage1"
        loc = 10
        break
if loc == 10:     #page 2 if needed
    loc = 580
    for info2 in pointtable2:
        recid2 = info2.ID
        if recid2 not in nlist:
            z+=1
            c.drawString(other rows...)
            nlist.append(recid2)
    c.showPage()
c.save()
output = PdfFileWriter()
file1 = PdfFileReader(file("outputmap.pdf", "rb")) #created map in this loop
file2 = PdfFileReader(file("ReceptorList.pdf", "rb")) #created receptor pdf         in loop
if z > 64:
    output.addPage(file1.getPage(0)) #map
    output.addPage(file2.getPage(0)) #page 1 list
    output.addPage(file2.getPage(1)) #page 2 list
    outputstream = file("FacilityName+.pdf", "wb") #naming new pdf fac_name
    output.write(outputstream) #merging both pdf's into one!
    outputstream.close()
else:
    output.addPage(file1.getPage(0)) #map
    output.addPage(file2.getPage(0)) #page 1 list
    outputstream = file("FacilityName+.pdf", "wb") #naming new pdf fac_name
    output.write(outputstream) #merging both pdf's into one!
    outputstream.close()

I am able to generate a multi page pdf for a receptor list but there are times when 2 pages is simply not enough and if i were to write more code to for more PDF pages for a receptor it would be very difficult to write because of all my counters, IF statements. Is there another way I can create multi page PDF's to merge to the map? Is there a reportlab method that can simply copy the receptor table to a PDF (even if it is multi page)

Best Answer

I had a similar problem four years ago and worked through it as https://stackoverflow.com/questions/9271370/how-to-repeat-table-column-headings-over-page-breaks-in-pdf-output-from-reportla

The code that I came up with was as below but basically I let ReportLab take care of the page breaks and just threw a table of any length at it:

from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Frame, Spacer
from reportlab.lib import colors
from reportlab.lib.units import cm
from reportlab.lib.pagesizes import A3, A4, landscape, portrait
from reportlab.lib.styles import ParagraphStyle, getSampleStyleSheet
from reportlab.lib.enums import TA_LEFT, TA_RIGHT, TA_CENTER, TA_JUSTIFY
from reportlab.pdfgen import canvas

pdfReportPages = "C:\\Temp\\test.pdf"
doc = SimpleDocTemplate(pdfReportPages, pagesize=A4)

# container for the "Flowable" objects
elements = []
styles=getSampleStyleSheet()
styleN = styles["Normal"]

# Make heading for each column and start data list
column1Heading = "COLUMN ONE HEADING"
column2Heading = "COLUMN TWO HEADING"
# Assemble data for each column using simple loop to append it into data list
data = [[column1Heading,column2Heading]]
for i in range(1,100):
    data.append([str(i),str(i)])

tableThatSplitsOverPages = Table(data, [6 * cm, 6 * cm], repeatRows=1)
tableThatSplitsOverPages.hAlign = 'LEFT'
tblStyle = TableStyle([('TEXTCOLOR',(0,0),(-1,-1),colors.black),
                       ('VALIGN',(0,0),(-1,-1),'TOP'),
                       ('LINEBELOW',(0,0),(-1,-1),1,colors.black),
                       ('BOX',(0,0),(-1,-1),1,colors.black),
                       ('BOX',(0,0),(0,-1),1,colors.black)])
tblStyle.add('BACKGROUND',(0,0),(1,0),colors.lightblue)
tblStyle.add('BACKGROUND',(0,1),(-1,-1),colors.white)
tableThatSplitsOverPages.setStyle(tblStyle)
elements.append(tableThatSplitsOverPages)

doc.build(elements)
Related Question