Skip to content

Panduan

Dokumentasi secara lengkap: fpdf.FPDF API doc

Panduan 1 - Contoh Sederhana

Mari kita mulai dengan contoh sederhana:

from fpdf import FPDF

pdf = FPDF()
pdf.add_page()
pdf.set_font("helvetica", "B", 16)
pdf.cell(40, 10, "Hello World!")
pdf.output("tuto1.pdf")

Hasil PDF

Setelah menyertakan file library tersebut, kita buat objek FPDF. Konstruktor FPDF yang digunakan ini mempunyai nilai bawaan: halaman dalam format kertas A4 portrait dan satuan pengukuran dalam milimeter. Ini juga dapat ditentukan secara eksplisit dengan:

pdf = FPDF(orientation="P", unit="mm", format="A4")

Kita juga dapat mengatur PDF dalam mode landscape (L) atau menggunakan format halaman lainnya (seperti Letter dan Legal) dan satuan ukuran (pt, cm, in).

Karena saat ini tidak ada halaman, kita harus menambahkannya dengan add_page. Titik awal kursor berada di pojok kiri atas dan posisi yang sekarang ditempatkan 1 cm dari margin secara default; margin dapat diubah dengan set_margins.

Sebelum kita dapat mencetak teks, penting untuk memilih font dengan set_font, jika tidak, dokumen akan menjadi tidak valid. Kita pilih font Helvetica dengan ketebalan 16:

pdf.set_font('helvetica', 'B', 16)

Kita dapat menentukan font italic dengan I, bergaris bawah dengan U, atau jenis font reguler dengan string kosong (atau kombinasi lain). Perlu dicatat bahwa ukuran font diberikan dalam satuan poin, bukan milimeter (atau satuan lainnya); ini adalah satu-satunya pengecualian. Font bawaan lainnya adalah Times, Courier, Symbol, dan ZapfDingbats.

Sekarang kita dapat mencetak cell dengan cell. Sebuah cell adalah area berbentuk persegi panjang yang berisi beberapa teks. Cell tersebut dirender pada posisi kursor saat ini. Kita tentukan dimensinya, teksnya (di tengah atau rata kiri/kanan), apakah garis batas akan digambar, dan di mana posisi kursor bergerak setelahnya (ke kanan, ke bawah, atau ke awal baris berikutnya). Untuk menambahkan frame, kita dapat melakukannya seperti ini:

pdf.cell(40, 10, 'Hello World!', 1)

Untuk menambahkan cell baru tepat disampingnya dengan teks rata tengah dan langsung ke baris selanjutnya, kita bisa:

pdf.cell(60, 10, 'Powered by FPDF.', new_x="LMARGIN", new_y="NEXT", align='C')

Komentar: line break atau menambah baris baru sekarang bisa dilakukan dengan ln. Method ini dapat menentukan tinggi dari baris baru tersebut.

Terakhir, dokumen di atas ditutup dan disimpan dalam file path yang ditentukan menggunakan output. Tanpa adanya parameter, output() akan menghasilkan PDF bytearray buffer.

Berikut adalah contoh dua halaman dengan header, footer dan logo:

from fpdf import FPDF


class PDF(FPDF):
    def header(self):
        # Rendering logo:
        self.image("../docs/fpdf2-logo.png", 10, 8, 33)
        # Setting font: helvetica bold 15
        self.set_font("helvetica", "B", 15)
        # Moving cursor to the right:
        self.cell(80)
        # Printing title:
        self.cell(30, 10, "Title", border=1, align="C")
        # Performing a line break:
        self.ln(20)

    def footer(self):
        # Position cursor at 1.5 cm from bottom:
        self.set_y(-15)
        # Setting font: helvetica italic 8
        self.set_font("helvetica", "I", 8)
        # Printing page number:
        self.cell(0, 10, f"Page {self.page_no()}/{{nb}}", align="C")


# Instantiation of inherited class
pdf = PDF()
pdf.add_page()
pdf.set_font("Times", size=12)
for i in range(1, 41):
    pdf.cell(0, 10, f"Printing line number {i}", new_x="LMARGIN", new_y="NEXT")
pdf.output("new-tuto2.pdf")

Hasil PDF

Contoh di atas menggunakan method header dan footer untuk memproses header dan footer halaman. Keduanya dipanggil secara otomatis. Keduanya sebenarnya sudah ada dalam class FPDF namun tidak melakukan apapun, sehingga kita harus meng-extend class tersebut dan menimpanya dengan preferensi kita.

Logo halaman dicetak dengan method image dan dengan menentukan sudut kiri atas dan lebarnya. Tinggi gambar akan dihitung secara otomatis untuk menjaga proporsi gambarnya.

Untuk mencetak nomor halaman, nilai kosong atau null akan di-passing sebagai lebar cell. Yang artinya, cell harus memanjang hingga margin kanan halaman; hal ini berguna agar teks rata tengah. Nomor halaman yang ada sekarang, dihasilkan oleh method page_no; sedangkan untuk jumlah total halaman, dapat diperoleh dengan nilai khusus yaitu {nb} yang akan diganti saat dokumen ditutup (nilai khusus tersebut dapat diubah dengan alias_nb_pages()). Perhatikan penggunaan method set_y yang dapat mengatur posisi dengan lokasi yang absolut dalam halaman, mulai dari atas atau bawah.

Fitur menarik lain yang digunakan disini adalah page break otomatis. Begitu cell sudah melewati batas di halaman (jarak 2cm dari bawah secara default), page break dilakukan dan font dikembalikan. Meskipun header dan footer memilih font mereka sendiri (helvetica), body halaman tetap menggunakan Times. Mekanisme pemulihan otomatis ini juga berlaku untuk warna dan lebar garis. Batas yang memicu page break dapat diatur dengan set_auto_page_break.

Panduan 3 - Line breaks dan warna

Mari kita lanjutkan dengan mencetak paragraf yang rata kiri dan kanan. Contoh ini juga akan mengilustrasikan penggunaan warna.

from fpdf import FPDF


class PDF(FPDF):
    def header(self):
        # Setting font: helvetica bold 15
        self.set_font("helvetica", "B", 15)
        # Calculating width of title and setting cursor position:
        width = self.get_string_width(self.title) + 6
        self.set_x((210 - width) / 2)
        # Setting colors for frame, background and text:
        self.set_draw_color(0, 80, 180)
        self.set_fill_color(230, 230, 0)
        self.set_text_color(220, 50, 50)
        # Setting thickness of the frame (1 mm)
        self.set_line_width(1)
        # Printing title:
        self.cell(
            width,
            9,
            self.title,
            border=1,
            new_x="LMARGIN",
            new_y="NEXT",
            align="C",
            fill=True,
        )
        # Performing a line break:
        self.ln(10)

    def footer(self):
        # Setting position at 1.5 cm from bottom:
        self.set_y(-15)
        # Setting font: helvetica italic 8
        self.set_font("helvetica", "I", 8)
        # Setting text color to gray:
        self.set_text_color(128)
        # Printing page number
        self.cell(0, 10, f"Page {self.page_no()}", align="C")

    def chapter_title(self, num, label):
        # Setting font: helvetica 12
        self.set_font("helvetica", "", 12)
        # Setting background color
        self.set_fill_color(200, 220, 255)
        # Printing chapter name:
        self.cell(
            0,
            6,
            f"Chapter {num} : {label}",
            new_x="LMARGIN",
            new_y="NEXT",
            align="L",
            fill=True,
        )
        # Performing a line break:
        self.ln(4)

    def chapter_body(self, filepath):
        # Reading text file:
        with open(filepath, "rb") as fh:
            txt = fh.read().decode("latin-1")
        # Setting font: Times 12
        self.set_font("Times", size=12)
        # Printing justified text:
        self.multi_cell(0, 5, txt)
        # Performing a line break:
        self.ln()
        # Final mention in italics:
        self.set_font(style="I")
        self.cell(0, 5, "(end of excerpt)")

    def print_chapter(self, num, title, filepath):
        self.add_page()
        self.chapter_title(num, title)
        self.chapter_body(filepath)


pdf = PDF()
pdf.set_title("20000 Leagues Under the Seas")
pdf.set_author("Jules Verne")
pdf.print_chapter(1, "A RUNAWAY REEF", "20k_c1.txt")
pdf.print_chapter(2, "THE PROS AND CONS", "20k_c1.txt")
pdf.output("tuto3.pdf")

Hasil PDF

Contoh teks Jules Verne

Method get_string_width dapat menentukan panjang string dalam sebuah font, yang digunakan untuk menghitung posisi dan lebar frame yang mengelilingi judul. Kemudian, warna dapat ditetapkan (melalui set_draw_color, set_fill_color dan set_text_color) dan ketebalan garis dapat ditetapkan ke 1 mm (dibandingkan 0,2 secara default) dengan set_line_width. Terakhir, kita output cell (parameter terakhir bernilai True menunjukkan bahwa background harus diisi).

Method yang digunakan untuk mencetak paragraf adalah multi_cell. Teks akan rata kiri dan kanan secara default. Setiap kali baris mencapai ujung kanan cell atau terdapat karakter carriage return (\n), akan dimunculkan line break dan cell baru akan otomatis dibuat di bawah cell tersebut. Pembatasan otomatis dilakukan di lokasi spasi terdekat atau karakter soft-hyphen (\u00ad) sebelum batas kanan halaman. Soft-hyphen akan diganti dengan tanda hubung biasa saat ada line break, dan diabaikan jika tidak.

Dua properti dokumen ditetapkan: judul (set_title) dan penulis (set_author). Properti tersebut dapat dilihat dengan dua cara. Pertama adalah dengan membuka dokumen secara langsung dengan Acrobat Reader, masuk ke menu File dan pilih opsi Document Properties. Yang kedua, juga tersedia dari plug-in, adalah klik kanan dan pilih Document Properties.

Panduan 4 - Multi Kolom

Contoh berikut adalah varian dari contoh sebelumnya, yang menunjukkan cara meletakkan teks di beberapa kolom.

from fpdf import FPDF


class PDF(FPDF):
    def header(self):
        self.set_font("helvetica", "B", 15)
        width = self.get_string_width(self.title) + 6
        self.set_x((210 - width) / 2)
        self.set_draw_color(0, 80, 180)
        self.set_fill_color(230, 230, 0)
        self.set_text_color(220, 50, 50)
        self.set_line_width(1)
        self.cell(
            width,
            9,
            self.title,
            border=1,
            new_x="LMARGIN",
            new_y="NEXT",
            align="C",
            fill=True,
        )
        self.ln(10)

    def footer(self):
        self.set_y(-15)
        self.set_font("helvetica", "I", 8)
        self.set_text_color(128)
        self.cell(0, 10, f"Page {self.page_no()}", align="C")

    def chapter_title(self, num, label):
        self.set_font("helvetica", "", 12)
        self.set_fill_color(200, 220, 255)
        self.cell(
            0,
            6,
            f"Chapter {num} : {label}",
            new_x="LMARGIN",
            new_y="NEXT",
            border="L",
            fill=True,
        )
        self.ln(4)

    def chapter_body(self, fname):
        # Reading text file:
        with open(fname, "rb") as fh:
            txt = fh.read().decode("latin-1")
        with self.text_columns(
            ncols=3, gutter=5, text_align="J", line_height=1.19
        ) as cols:
            # Setting font: Times 12
            self.set_font("Times", size=12)
            cols.write(txt)
            cols.ln()
            # Final mention in italics:
            self.set_font(style="I")
            cols.write("(end of excerpt)")

    def print_chapter(self, num, title, fname):
        self.add_page()
        self.chapter_title(num, title)
        self.chapter_body(fname)


pdf = PDF()
pdf.set_title("20000 Leagues Under the Seas")
pdf.set_author("Jules Verne")
pdf.print_chapter(1, "A RUNAWAY REEF", "20k_c1.txt")
pdf.print_chapter(2, "THE PROS AND CONS", "20k_c1.txt")
pdf.output("tuto4.pdf")

Hasil PDF

Contoh teks Jules Verne

Perbedaan utama dari tutorial sebelumnya adalah penggunaan method text_columns. Method tersebut mengumpulkan semua teks secara bertahap dan mendistribusikan ke sejumlah kolom yang diminta, secara otomatis memasukkan page break jika diperlukan. Perlu diperhatikan bahwa saat instance TextColumns aktif sebagai context manager, gaya teks dan properti font lainnya dapat diubah. Perubahan tersebut akan dibatasi sesuai pada context dalam context manager. Setelah ditutup, pengaturan sebelumnya akan dikembalikan.

Panduan 5 - Membuat tabel

Panduan ini akan menjelaskan tentang cara membuat dua tabel berbeda dengan beberapa penyesuaian sederhana.

import csv
from fpdf import FPDF
from fpdf.fonts import FontFace
from fpdf.enums import TableCellFillMode


with open("countries.txt", encoding="utf8") as csv_file:
    data = list(csv.reader(csv_file, delimiter=","))

pdf = FPDF()
pdf.set_font("helvetica", size=14)

# Basic table:
pdf.add_page()
with pdf.table() as table:
    for data_row in data:
        row = table.row()
        for datum in data_row:
            row.cell(datum)

# Styled table:
pdf.add_page()
pdf.set_draw_color(255, 0, 0)
pdf.set_line_width(0.3)
headings_style = FontFace(emphasis="BOLD", color=255, fill_color=(255, 100, 0))
with pdf.table(
    borders_layout="NO_HORIZONTAL_LINES",
    cell_fill_color=(224, 235, 255),
    cell_fill_mode=TableCellFillMode.ROWS,
    col_widths=(42, 39, 35, 42),
    headings_style=headings_style,
    line_height=6,
    text_align=("LEFT", "CENTER", "RIGHT", "RIGHT"),
    width=160,
) as table:
    for data_row in data:
        row = table.row()
        for datum in data_row:
            row.cell(datum)

pdf.output("tuto5.pdf")

Hasil PDF - Data CSV Negara-negara

Contoh pertama dapat dicapai dengan cara yang mudah, yaitu memasukkan data ke FPDF.table(). Hasil yang didapatkan memang sangat simpel, tetapi sangat cepat untuk dibuat.

Tabel kedua menghadirkan beberapa perbaikan: warna, lebar tabel yang dibatasi, tinggi baris yang berkurang, judul dengan rata tengah, kolom dengan lebar custom, gambar yang rata kanan... Selain itu, garis horizontal telah dihapus. Hal ini dilakukan dengan memilih border_layout di antara nilai yang tersedia: TableBordersLayout.

Panduan 6 - Membuat tautan dan mencampur gaya teks

Dalam panduan ini akan dijelaskan beberapa cara untuk menyisipkan tautan di dalam dokumen PDF, serta menambahkan tautan ke sumber eksternal.

Panduan ini juga akan menunjukkan beberapa cara untuk menggunakan gaya teks yang berbeda, (tebal, miring, garis bawah) dalam teks yang sama.

from fpdf import FPDF


pdf = FPDF()

# First page:
pdf.add_page()
pdf.set_font("helvetica", size=20)
pdf.write(5, "To find out what's new in self tutorial, click ")
pdf.set_font(style="U")
link = pdf.add_link(page=2)
pdf.write(5, "here", link)
pdf.set_font()

# Second page:
pdf.add_page()
pdf.image(
    "../docs/fpdf2-logo.png", 10, 10, 50, 0, "", "https://py-pdf.github.io/fpdf2/"
)
pdf.set_left_margin(60)
pdf.set_font_size(18)
pdf.write_html(
    """You can print text mixing different styles using HTML tags: <b>bold</b>, <i>italic</i>,
<u>underlined</u>, or <b><i><u>all at once</u></i></b>!
<br><br>You can also insert links on text, such as <a href="https://py-pdf.github.io/fpdf2/">https://py-pdf.github.io/fpdf2/</a>,
or on an image: the logo is clickable!"""
)
pdf.output("tuto6.pdf")

Hasil PDF - Logo fpdf2

Method baru yang ditunjukkan disini untuk mencetak teks adalah write() . Ini sangat mirip dengan multi_cell() , perbedaan utamanya adalah:

  • Akhir baris berada di margin kanan dan baris berikutnya dimulai di margin kiri.
  • Posisi kursor berpindah ke akhir teks.

Oleh karena itu, method ini dapat digunakan untuk menulis sepotong teks, mengubah gaya font, dan melanjutkan dari tempat yang sama persis dengan tempat terakhir kursor berhenti. Di sisi lain, kelemahan utamanya adalah kita tidak bisa membuat teks rata kiri dan kanan seperti saat menggunakan method multi_cell().

Pada halaman pertama contoh, kita menggunakan write(). Awal kalimat ditulis dalam gaya teks biasa, kemudian menggunakan method set_font(), kita ganti menggunakan garis bawah dan mengakhiri kalimatnya.

Untuk menambahkan tautan internal yang mengarah ke halaman kedua, kita dapat menggunakan method add_link(), yang membuat area yang dapat diklik yang biasa disebut "link" yang mengarah ke halaman lain dalam dokumen.

Untuk membuat tautan eksternal menggunakan gambar, kita dapat menggunakan image(). Method ini mempunyai opsi untuk passing tautan sebagai salah satu argumennya. Tautan tersebut dapat berupa tautan internal atau eksternal.

Sebagai alternatif, opsi lain untuk mengubah gaya font dan menambahkan tautan adalah dengan menggunakan method write_html(). Method tersebut merupakan parser HTML yang dapat menambahkan teks, mengubah gaya font, dan menambahkan tautan menggunakan HTML.