CodeX
Published in

CodeX

Create a Custom PDF using Python

In this article, I will show you how we can create a PDF using Python with FPDF library. By default, FPDF only support certain languages, so I will also go through the steps required to use more languages with FPDF.

Learning Outcomes:

  1. What are FPDF, PyFPDF, and tFPDF?
  2. The basic functions of FPDF with Python.
  3. Multi-language support in FPDF.
  4. Make a simple PDF with me in this article.
Source: https://unsplash.com/

What is FPDF?

FPDF is a PHP class that allows to generate PDF files with pure PHP. F from FPDF stands for Free: you may use it for any kind of usage and modify it to suit your needs. It is quite a popular choice to generate PDF.

PyFPDF

Ported from PHP FPDF, PyFPDF is a library for PDF document generation under Python. This is the library we will install and use. The basic functions explained below are coming from this library too.

tFPDF

A modified version of FPDF that adds UTF-8 support to produce documents in many languages as long as you provide the fonts. You will require PHP installed in your machine to use this PHP class.

If you want to see how to add other languages to your PDF straight away, go the last section.

Main Features

FPDF provides a list of ready-to-use high-level functions :

  • Choice of measure unit, page format, and margins
  • Page header and footer management
  • Automatic page break
  • Automatic line break and text justification
  • Image support (JPEG, PNG, and GIF)
  • Colors
  • Links
  • TrueType, Type1, and encoding support
  • Page compression

In this section, I will show you how to install the FPDF and use its basic functions, open a new Python file and follow along!

Source: gfycat.com

Installation

$ pip install fpdf

Start a FPDF

In a python file, we will first import and create an FPDF object.

from fpdf import FPDF

pdf = FPDF('P', 'mm', 'A4')
pdf.add_page()
pdf.set_margins(0, 0, 0)

The FPDF object above uses the default values: pages are in portrait with the measure unit millimeter and A4 format. You can use landscape (L), measure units (pt, cm, in), and other page formats (such as Letter and Legal).

Then we add one new page with pdf.add_page(). The origin is at the upper-left corner and the current position is by default placed at 1 cm from the borders. The margins can be changed with pdf.set_margins().

Generate PDF

pdf.output('sample.pdf', 'F')

Save the PDF to a local file with the given name ‘sample.pdf’. Follow the steps below and rerun the python file to see the difference when new lines are added.

If you are creating the PDF file for the first time, it may take some time, then it will be faster the next time.

Always place this line at the bottom of your code.

Add Your First Line in PDF

pdf.set_font('Arial', 'B', 14)
pdf.cell(w = 40, h = 10, 'Hello World!', border = 0, ln = 1, align = '', fill = False, link = '')

Before we can print text, it is mandatory to select a font with pdf.set_font(). We can specify italics with I, underlined with U and even both italics and bold with BI. The other standard fonts are Times, Courier, Symbol, and ZapfDingbats.

A cell is a rectangular area that can hold the content. We specify its dimensions (w, h), its text, if borders should be drawn, where the current position moves after it (to the right, below, or to the beginning of the next line), its text alignment, shape fill, and link attachment.

Add New Line

pdf.set_font('Times', '', 12)
pdf.cell(210, 10, 'Powered by FPDF.', 0, 0, 'C')

Then let’s add a new line with another font. The new cell will be on the next line as we had ln=1 at the previous pdf.cell() which specifies the position of the next line. Also, it is centered in its cell dimension without a border.

Manage Your Text Position

pdf.set_font('Arial', '', 12)
pdf.ln(50)
pdf.cell(85)
pdf.cell(0, 0, 'We have a new line.', 0)

To go to the next line, personally I prefer using ln which allows you to specify the height of the break. If you would notice, the pdf.ln() and pdf.cell() actually start counting from the top-left position of our second line, ‘Powered by FPDF.’ The pdf.ln() and pdf.cell() are acting like a cursor which it start from where it is pointing to and move to next with specified height and width by pdf.ln() and pdf.cell().

It is a good way to position your text if you want to create a complex pdf like a receipt with texts that are not arranged line by line. But if you only want to generate a tidy document with some text and perhaps images, you can easily do it by specifying the position of the next line in the pdf.cell() arguments.

Also, a tip to measure the position of the text if you already have a dummy template is to use the ruler in a word editor.

Add Image

pdf.image('cat_in_the_snow.jpg', x = 85, y = 32.5, w = 40, h = 0, type = '', link = '')

We would specify the coordinate (x, y) of the top left corner for the image. Also, the width of the image (w), its height will be automatically calculated if not specified.

Draw a Line

pdf.line(x1 = 85, y1 = 27.5, x2 = 125, y2 = 27.5)

It is pretty easy to draw the line with FPDF, we just have to specify the coordinates, (x1, y1) and (x2, y2), of two endpoints of the line.

Notice that both image and line are not affected by the pdf.ln() and pdf.cell() current pointing position. They will affect only the position of cells.

Draw a Rectangle or Ellipse

pdf.rect(x = 80, y = 20, w = 50, h = 55, style = '')

Draw a rectangle without any effort by setting the top-left position (x, y) and the dimension (w, h) of your rectangle. Alternatively, draw a cell with a border will do the same, both of them are able to do color fill.

Draw (D) is the default style, you can change the style with fill (F) or draw and fill (DF or FD).

Similarly, you can draw an ellipse with pdf.ellipse().

Set color

pdf.set_fill_color(128, 166, 197)
pdf.set_draw_color(41, 53, 50)
pdf.rect(80, 115, 50, 10, 'DF')

pdf.set_text_color(183, 208, 232)
pdf.ln(50)
pdf.cell(70)
pdf.cell(70, 0, 'We have a new line.', 0, 0, 'C')

We can set color for the following cell, line, or shape with the code above.

That’s all I will cover for the basic functions of FPDF, if you need more resources to do what you need, check out the reference manual by PyFPDF.

Before we move on to the last section, let’s have a popcat border.

for i in range(17):
pdf.image('popcat.gif', 20 + i * 10, 102.5, 5)
pdf.image('popcat.gif', 20 + i * 10, 82.5, 5)
pdf.image('popcat2.jpg', 25 + i * 10, 102.5, 5)
pdf.image('popcat2.jpg', 25 + i * 10, 82.5, 5)
Source: monkeyuser.com

Finally, let’s talk about how you can use multiple languages in the PDF.

Enable Other Languages

If you are finding a solution to works with multi-language in FPDF, you may face the problem already which the text printed out is a list of rectangles ▯▯▯▯ while what you want to show is four letters, eg. “欢迎光临”. Or no better, a Unicode Encode Error pop out.

I will show how to include more languages font with tFPDF. There may be other solutions like Chinese support for FPDF, a plugin for Japanese, or even use another PDF generator TCPDF (under development). However, I found tFPDF with FPDF the best which it is quite simple to set up and you can use it for many languages and fonts.

Setup:

  1. Install PHP in your machine.
  • I would suggest an All-in-One package like XAMPP, some weird stuff might happen that requires you to edit php.ini to enable mbstring extension if you install PHP alone.

2. Download the tFPDF.zip or download from this site.

3. What you will need is only the tfpdf.php and font/ folder. Place them under your current directory. The rest are some example files, feel free to test them out.

4. Include the following lines at the top of your python file :

from fpdf import FPDF
import subprocess
subprocess.call(["php", "tfpdf.php"], shell=True)
font_path = './font/unifont/'

5. Nice! We are nearly there. Let’s add the font you want to use by pdf.add_font().

  • There are already some fonts ready in the font/ folder which you can use straight away. The fonts under font/unifont/ needed to be added with pdf.add_font() to use them.
  • You can add more fonts in .ttf format into the font/unifont/ . In my GitHub link below, you can find the Simsun font that I show here.
  • However, a setback is not all .ttf fonts can be used with tFPDF, testing is required to find out the workable fonts.
pdf.add_font('Simsun', '', font_path + 'SIMSUN.ttf', uni=True)

6. Set the font and use it.

pdf.set_text_color(0, 0, 0)
pdf.set_font('Simsun', '', 22)
pdf.ln(-24)
pdf.cell(90)
pdf.cell(0, 0, '欢迎光临', 0)

If you have followed our code thoroughly, you will be able to generate the PDF file with the content shown below:

Github

You can find the code all above at this site.

References

  1. http://www.fpdf.org/
  2. http://www.fpdf.org/en/script/script92.php
  3. https://pyfpdf.readthedocs.io/en/latest/
  4. https://pyfpdf.readthedocs.io/en/latest/reference/image/index.html

About Author

This article is written by Han Sheng, Junior Artificial Intelligence Engineer in CertifAI, Penang, Malaysia. He has a passion for Deep Learning, Computer Vision and also Edge Devices. He made several AI-based Web/Mobile Applications to help clients solving real-world problems. Feel free to read about him via his portfolio or Github profile.

--

--

--

Everything connected with Tech & Code. Follow to join our 900K+ monthly readers

Recommended from Medium

Simple Hacks using Computer Vision

Using Bash Automated Testing System to Test Your Azure Pipelines Custom Logic

How Many Documents Can Be Signed With PandaDoc

Bypassing paywalls: The need-to-know for digital publishers.

Streaming Dota 2

Simple Solution to Embarrassing Collapses of Census Website due to Poor Load Testing

ZKSpace Weekly Dev & Operations Report (1.1–1.7)

Gradle Sync on Corporate Network/Secure Network/Proxy Network

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Draden Liang Han Sheng

Draden Liang Han Sheng

Full Stack AI Application Development | Computer Vision | Deep Learning | Edge Devices

More from Medium

Dashboard Tale: Flask, Dash and Plotly

A GUI for Pandas / Bamboolib

Python — JSONDecodeError

An Easy Beginners Guide to SQLite in Python and Pandas