Python reportlab dynamically create new page after first page is completely filled with text

Viewed 1542

Python 3.8 x64 | Windows 10 x64 | reportlab v3.5.46 (open-source)

Been searching everywhere for an answer on this to no avail. I just want to create a PDF document that contains a lot of text. After the first page is completely full of text, the remaining text should flow onto a second page. After the second page is completely full of text, the remaining text should flow onto a third page (and so on)...

All answers I find searching around the world via the internet states to use the canvas.showPage() method. This is not a great solution because in all of these examples the first page is not completely populated with text hence it is a manual method of adding a new page. In my example I do not know when the first page will be filled with text thus I do not know when I need to create a second or new page using canvas.showPage().

I need to somehow detect when the first page cannot hold any more text, and when this occurs create a new page to hold the text which remains.

From reading over the reportlabs documentation, I am not sure how to achieve this in a practical pythonic implementation. There are also platypus.PageBreak() and BaseDocTemplate.afterPage() methods but not sure what they do because the documentation is sparse on these methods.

I don't think the code I am using will be much value for my question, but it is included below for reference. The function parameter my_text is a multi-page amount of text.

from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.pagesizes import LETTER
from reportlab.lib.units import inch


def create_pdf_report_text_object(my_text):
    canvas = Canvas('Test.pdf', pagesize=LETTER)
    canvas.setFont('Helvetica', size=10)
    text_object = canvas.beginText(x=1 * inch, y=10 * inch)

    for line in my_text.splitlines(False):
        text_object.textLine(line.rstrip())

    canvas.drawText(text_object)
    canvas.save()
1 Answers

I believe one solution to your question is to use a frame, this means the frame is re-created on every page until text runs out. The frame will detect when it is full.

Please see below example as a start to your own solution (its complete, just copy and paste and run the code, a pdf called "Example_output.pdf" should be created).

from reportlab.lib.pagesizes import letter
from reportlab.platypus import Paragraph
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import BaseDocTemplate, PageTemplate, Flowable, FrameBreak, KeepTogether, PageBreak, Spacer
from reportlab.platypus import Frame, PageTemplate, KeepInFrame
from reportlab.lib.units import cm
from reportlab.platypus import (Table, TableStyle, BaseDocTemplate)

styleSheet = getSampleStyleSheet()

########################################################################

def create_pdf():
    """
    Create a pdf
    """

    # Create a frame
    text_frame = Frame(
        x1=3.00 * cm,  # From left
        y1=1.5 * cm,  # From bottom
        height=19.60 * cm,
        width=15.90 * cm,
        leftPadding=0 * cm,
        bottomPadding=0 * cm,
        rightPadding=0 * cm,
        topPadding=0 * cm,
        showBoundary=1,
        id='text_frame')

    # Create text

    L = [Paragraph("""What concepts does PLATYPUS deal with?""", styleSheet['Heading2']),
                          Paragraph("""
                         The central concepts in PLATYPUS are Flowable Objects, Frames, Flow
                         Management, Styles and Style Sheets, Paragraphs and Tables.  This is
                         best explained in contrast to PDFgen, the layer underneath PLATYPUS.
                         PDFgen is a graphics library, and has primitive commans to draw lines
                         and strings.  There is nothing in it to manage the flow of text down
                         the page.  PLATYPUS works at the conceptual level fo a desktop publishing
                         package; you can write programs which deal intelligently with graphic
                         objects and fit them onto the page.
                         """, styleSheet['BodyText']),

                          Paragraph("""
                         How is this document organized?
                         """, styleSheet['Heading2']),

                          Paragraph("""
                         Since this is a test script, we'll just note how it is organized.
                         the top of each page contains commentary.  The bottom half contains
                         example drawings and graphic elements to whicht he commentary will
                         relate.  Down below, you can see the outline of a text frame, and
                         various bits and pieces within it.  We'll explain how they work
                         on the next page.
                         """, styleSheet['BodyText']),
                          ]






    # Building the story
    story = L * 20 # (alternative, story.add(L))
    story.append(KeepTogether([]))

    # Establish a document
    doc = BaseDocTemplate("Example_output.pdf", pagesize=letter)

    # Creating a page template
    frontpage = PageTemplate(id='FrontPage',
                             frames=[text_frame]
                             )
    # Adding the story to the template and template to the document
    doc.addPageTemplates(frontpage)

    # Building doc
    doc.build(story)


# ----------------------------------------------------------------------
if __name__ == "__main__":
    create_pdf() # Printing the pdf 
Related