Search code examples
pythoncanvasreportlab

How can i add another page to a PDF with canvas?


I developed an application to list the open fees of some clients, based on a spreadsheet and save it in a PDF. The code works perfectly, however when saving to PDF, in case the number of open fees is very large, the content of the page is cut, but another page is not added.

Here is the code below:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from tkinter import *
from tkinter import ttk
from tkinter import messagebox
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
import openpyxl
import os

pastaApp = os.path.dirname(__file__)

def createPDF():
    # Opens the spreadsheet and obtains the status of the last payment.

    wb = openpyxl.load_workbook('C:/temp/cobranca.xlsx')
    sheet = wb['Sheet1']

    lastCol = sheet.max_column

    # Checks the payment status of each customer.

    unpaidMembers = {}
    clients = []
    months = []
    emails = []
    for r in range(2, sheet.max_row + 1):
        for c in range(3, lastCol + 1):
            payment = sheet.cell(row=r, column=c).value
            if payment != 'ok':
                client = sheet.cell(row=r, column=1).value
                email = sheet.cell(row=r, column=2).value
                month = sheet.cell(row=1, column=c).value
                clients.append(client)
                months.append(month)
                emails.append(email)
                unpaidMembers[client] = email
                #print('Line:', r, 'Column:', c, 'Client:', client, 'Email:', email, 'Month:', month)
                print('dictionary created successfully')

    cnv = canvas.Canvas(pastaApp+"\\test.pdf", pagesize=letter)
    cnv.drawString(10, 800, "Open Fee")
    cnv.drawString(130, 800, " - Client/Month/E-mail")
    y = 780
    for client, month, email in zip(clients, months, emails):
        cnv.drawString(10, y, client)
        cnv.drawString(170, y, month)
        cnv.drawString(350, y, email)
        y -= 20
        
    cnv.save()

root = Tk()
root.title("Create PDF")

btn_createPDF = Button(root, text="Check", command=createPDF)
btn_createPDF.pack(side="left", padx=10)

root.mainloop()

Spreadsheet model used:https://prnt.sc/125pi9y


Solution

  • You need to check the value of y in your for loop. If it goes below 36 (for half-inch margins), then call cnv.showPage(), reset y, and print a new header.

        cnv = canvas.Canvas(pastaApp+"\\test.pdf", pagesize=letter)
        cnv.drawString(10, 800, "Open Fee")
        cnv.drawString(130, 800, " - Client/Month/E-mail")
        y = 780
        for client, month, email in zip(clients, months, emails):
            cnv.drawString(10, y, client)
            cnv.drawString(170, y, month)
            cnv.drawString(350, y, email)
            y -= 20
            if y < 36:
                cnv.showPage()
                cnv.drawString(10, 800, "Open Fee")
                cnv.drawString(130, 800, " - Client/Month/E-mail")
                y = 780
    

    Separating the page header printer into a separate function is left as an exercise for the reader.