Fundor333

Letterhead With ReportLab


Letterhead With ReportLab

2021-05-03 | dev fingerfood coding pdf python reportlab
Reading time 3 minutes | Word count 479 |

Sometime you need to make some pdf looking more professional. In python you use the ReportLab1 package for make Pdf.

Fist the main core

For every document type I need I write a class with a get_pdf for print2 a Pdf.

Here an example3

class BasicPrinter:
    def __init__(self, buffer, pagesize="A4"):
        self.buffer = buffer
        if pagesize == "A4":
            self.pagesize = A4
        elif pagesize == "Letter":
            self.pagesize = letter
        else:
            self.pagesize = A4
        self.width, self.height = self.pagesize

    @staticmethod
    def _header_footer(canvas, doc):
        BasicPrinter.header(canvas, doc)
        BasicPrinter.footer(canvas, doc)

        canvas.saveState()
        canvas.restoreState()

    @staticmethod
    def header(canvas, doc):
        canvas.saveState()
        header = Image("letterhead_header.jpg", 600, 60)
        header.drawOn(
            canvas, doc.leftMargin - 2 * cm, doc.height + doc.topMargin + 2 * cm
        )
        canvas.restoreState()

    @staticmethod
    def footer(canvas, doc):
        canvas.saveState()
        footer = Image("letterhead_footer.jpg", 600, 60)
        w, h = footer.wrap(doc.width, doc.bottomMargin)
        footer.drawOn(canvas, doc.leftMargin - 2 * cm, h - 2 * cm)
        canvas.restoreState()

The real important things are the footer and header function (in our case staticmethod). In each one we add a img (the footer or header) with all the logos and company info in it. If you want you can put the info as text yourself. Remember to save and restore alwayse the canvas because sometime, if you don’t do it can launch error.

The specific printer (or how to use the main core)

After you have done you need to make a “printer” for your document. In this case is a booring paper about Privacy.

class PrivacyPaperPrinter(BasicPrinter):
    @staticmethod
    def _header_footer(canvas, doc):
        # Save the state of our canvas so we can draw on it 
        PrivacyPaperPrinter.header(canvas, doc)
        PrivacyPaperPrinter.footer(canvas, doc)

    def get_pdf(self):
        buffer = self.buffer
		styles = getSampleStyleSheet()
        doc = SimpleDocTemplate(buffer)

        elements = []
        elements.append(Paragraph("My boring Privacy Paper", style=styles["Title"]))
        elements.append(Paragraph("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi sed sem ornare, dictum sapien at, egestas sapien. Nullam faucibus eleifend finibus. Vivamus vel sapien urna.", style=styles["Normal"]))
        doc.build(elements, onFirstPage=self._header_footer, onLaterPages=self._header_footer)

        pdf = buffer.getvalue()
        buffer.close()
        return pdf

This class extend the previus one and fill the buffer with al the relevant info and other element of the document (like titles, paragraphs, tables and images).

For the way I set up this class you have all the page with the letterhead template. This is happening because I setup the onFirstPage which will be call on the first page and the onLaterPages which will be call from page two with the call for the header and the footer function.


  1. ReportLab is an opensource engine for Pdf documents. The python package is here  ↩︎

  2. I use print for the action of making a Pdf from some data (like a json, a csv or a datasource of other type) If one ore more of this Pdf’s types have a common layout (like a letterhead) I make an parent object for the type of document and call it SomethingPrinter↩︎

  3. My default paper is A4 but you can import any format from reportlab.lib.pagesizes or define a new one following this format A4 = (210mm,297mm) ↩︎

Mentions and response

Respond to this post on your own site. If you do, send me a webmention here.

Find out more about webmentions on the IndieWeb.