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)
2 Answers 2
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)
-
wow thanks, I will have to take a hard look at this to understand and apply thisziggy– ziggy2016年03月18日 03:08:56 +00:00Commented Mar 18, 2016 at 3:08
-
Unfortunately, I have forgotten a lot of what I learned at the time but there are a few other Q&As at Stack Overflow that I initiated that may be helpful. That will be the best site to research/ask about anything ReportLab specific.2016年03月18日 03:34:43 +00:00Commented Mar 18, 2016 at 3:34
-
@PolyGeo figured out how to write to multi page pdfs and merge them in clear succinct code
c.drawstring('columns headers')
c.drawstring('columns headers')etc..
nlist = []
loc = 545
z=0
for info in pointtable: #page 1
recid = info.ID #example rows
c.drawString(30, loc, recid)
c.drawString(other rows...)
loc = loc-10
z+=1
nlist.append(recid) #storing id in list
if loc <= 10:
c.showPage()
loc = 580
c.save()
print "PDF Receptor Report"
def append_pdf(input,output):
[output.addPage(input.getPage(page_num)) for page_num in range(input.numPages)]
output = PdfFileWriter()
append_pdf(PdfFileReader(open("mappath"+".pdf", "rb")),output)
append_pdf(PdfFileReader(open("pathReceptorList"+".pdf", "rb")),output)
output.write(open("name of map"+.pdf", "wb"))