Letterhead With ReportLab

Fundor333
3 min readMay 3, 2021

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

Fist the main core

For every document type I need I write a class with a get_pdf for print² a Pdf. 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.

Here an example³:

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 always 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 boring 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 previous 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)
  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 = (210*mm,297*mm)

--

--

Fundor333
Fundor333

Written by Fundor333

A Python developer who work on Wordpress projects and make automation scripts. Sometime a Nerd, sometime a Geek always time for tea

No responses yet