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.
- What are FPDF, PyFPDF, and tFPDF?
- The basic functions of FPDF with Python.
- Multi-language support in FPDF.
- Make a simple PDF with me in this article.
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.
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.
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.
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)
- 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!
$ 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().
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.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.
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().
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.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)
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.
- 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.inito enable mbstring extension if you install PHP alone.
3. What you will need is only the
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
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
.ttfformat into the
font/unifont/. In my GitHub link below, you can find the
Simsunfont that I show here.
- However, a setback is not all
.ttffonts 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.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:
You can find the code all above at this site.
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.