Conditional page break in reportlab

I create PDFs tables with platypus Reportlab. I do not know when the page is full due to dynamic content. How can I check if I am at the end of the page?

Is there any method in the platypus to check the end of the page?

I have a list of companies, and each company has several business units with their own responsibilities.

companies = [('company1', 'businessunit1', 500), ('company1', 'businessunit2',400), ('company2', 'businessunit3',200), ('company2', 'businessunit4', 700), ('company3', 'businessunit5', 800) ] 

The above list should generate 3 tables for each company, but if there are several companies in this list that generate several tables and if any table reaches the end of the page that will break.

  fields = ['company name', 'business unit name', 'charge'] for i, comp in enumerate(companies): charges = [] document.append(Paragraph("<b>%s</b>" %comp[i][0], STYLES['COMPANY_NAME'])) document.append(Spacer(1, 5)) charges.append(comp[i][0]) charges.append(comp[i][1]) charges.append(comp[i][2]) charges_table = LongTable([fields] + charges, colWidths=(30,150,100)) charges_table.setStyle(TableStyle([ ('BACKGROUND', (0, 0), (-1, 0), colors.gray), ('FONTSIZE', (0, 0), (-1, 0), 6), ('GRID', (0, 0), (-1, -1), 1, colors.gray), ('FONTSIZE', (0, 0), (-1, -1), 7), ('TEXTCOLOR',(0,-1),(-1,-1),'#FF4500'), ]) ) charges_table.hAlign = 'CENTER' document.append(charges_table) 
+7
source share
4 answers

You should provide sample code so that we know what you are trying to accomplish. Why do you want to know when the page has ended? Create new content? To print some diagnostic information?

Assuming you want to draw something after the page is displayed, you can use the afterPage() method, which is provided in the BaseDocTemplate class. From the ReportLab documentation:

This is called after processing the page and immediately after the afterDrawPage method of the current page template. A derived class can use this to perform actions that depend on the information on the page, for example, on the first and last word on a dictionary page.

Basically, it is called by BaseDocTemplate after the page has been drawn. In the source code, it includes self , as it is part of the BaseDocTemplate class, so you can access its canvas!

You can override the class in your own script and then draw directly onto the canvas.

 from reportlab.platypus import BaseDocTemplate from reportlab.lib.styles import getSampleStyleSheet from reportlab.lib.units import inch from reportlab.lib.pagesizes import A4 from reportlab.platypus import Paragraph class MyDocTemplate(BaseDocTemplate): """Override the BaseDocTemplate class to do custom handle_XXX actions""" def __init__(self, *args, **kwargs): BaseDocTemplate.__init__(self, *args, **kwargs) def afterPage(self): """Called after each page has been processed""" # saveState keeps a snapshot of the canvas state, so you don't # mess up any rendering that platypus will do later. self.canv.saveState() # Reset the origin to (0, 0), remember, we can restore the # state of the canvas later, so platypus should be unaffected. self.canv._x = 0 self.canv._y = 0 style = getSampleStyleSheet() p = Paragraph("This is drawn after the page!", style["Normal"]) # Wraps and draws the paragraph onto the canvas # You can change the last 2 parameters (canv, x, y) p.wrapOn(self.canv, 2*inch, 2*inch) p.drawOn(self.canv, 1*inch, 3*inch) # Now we restore the canvas back to the way it was. self.canv.restoreState() 

Now you can use MyDocTemplate in the same way you would use BaseDocTemplate in your main logic:

 if __name__ == "__main__": doc = MyDocTemplate( 'filename.pdf', pagesize=A4, rightMargin=.3*inch, leftMargin=.3*inch, topMargin=.3*inch, bottomMargin=.3*inch ) elements = [ # Put your actual elements/flowables here, however you're generating them. ] doc.addPageTemplates([ # Add your PageTemplates here if you have any, which you should! ]) # Build your doc with your elements and go grab a beer doc.build(elements) 
+4
source

You must count the lines used. I use a procedure that includes:

 lin += inc if lin > 580: doc.append(PageBreak()) lin = 5 

Knowing how many rows a table uses, you can find out if it matches the rest of the page.

I use "point" counting, so I can deal with lines of different heights.

0
source

To split a table into several pages, you must use your own templates in accordance with How to split a ReportLab table into a PDF page (next)?

Tables should break automatically when they reach the end of the page. But here is another example:

0
source

automatic division of a long table into several pages, for example:

 from reportlab.platypus import LongTable, TableStyle, BaseDocTemplate, Frame, PageTemplate from reportlab.lib.pagesizes import letter from reportlab.lib import colors def test(): doc = BaseDocTemplate( "test.pdf", pagesize=letter, rightMargin=72, leftMargin=72, topMargin=72, bottomMargin=18, showBoundary=True) elements = [] datas = [] for i, x in enumerate(range(1, 50)): datas.append([i, x]) t = LongTable(datas) tableStyle = [ ('INNERGRID', (0, 0), (-1, -1), 0.25, colors.black), ('BOX', (0, 0), (-1, -1), 0.25, colors.black), ] t.setStyle(TableStyle(tableStyle)) elements.append(t) frame = Frame( doc.leftMargin, doc.bottomMargin, doc.width, doc.height, id='normal') doc.addPageTemplates([PageTemplate(id='longtable', frames=frame)]) doc.build(elements) if __name__ == '__main__': test() 
0
source

All Articles