Skip to content

Tutorial

Pełna dokumentacja metod: fpdf.FPDF API doc

Tuto 1 - Minimalny Przykład

Zacznijmy od klasycznego przykładu:

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")

Plik wynikowy PDF

Po dołączeniu pliku biblioteki tworzymy obiekt FPDF. Używany jest tutaj konstruktor FPDF z domyślnymi wartościami: strony są w formacie A4 w pionie, a jednostką miary jest milimetr. Można było to określić jawnie za pomocą:

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

Możliwe jest ustawienie formatu PDF w trybie poziomym (L) lub użycie innych formatów stron. (takich jak Letter i Legal) oraz jednostek miary (pt, cm, in).

Na razie nie ma strony, więc musimy ją dodać za pomocą add_page. Początek znajduje się w lewym górnym rogu, a bieżąca pozycja domyślnie ustawiona jest na 1 cm od krawędzi; marginesy można zmienić za pomocą set_margins.

Zanim będziemy mogli drukować tekst, konieczne jest wybranie czcionki za pomocą set_font, w przeciwnym razie dokument będzie nieprawidłowy. Wybieramy czcionkę Helvetica pogrubioną o rozmiarze 16:

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

Można było określić kursywę za pomocą I, podkreślenie za pomocą U lub zwykłą czcionkę za pomocą pustego łańcucha (lub dowolnej kombinacji). Należy pamiętać, że rozmiar czcionki jest podany w punktach, a nie w milimetrach (lub innej jednostce użytkownika); jest to jedyny wyjątek. Inne wbudowane czcionki to Times, Courier, Symbol i ZapfDingbats.

Teraz możemy wydrukować komórkę za pomocą cell. Komórka to prostokątny obszar, ewentualnie obramowany, zawierający tekst. Jest renderowany w bieżącej pozycji. Określamy jej wymiary, jej tekst (wyśrodkowany lub wyrównany), czy powinny być rysowane ramki i gdzie przesunie się bieżąca pozycja po niej (w prawo, poniżej lub na początek następnego wiersza). Aby dodać ramkę, postępujemy tak:

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

Aby dodać obok niego nową komórkę z wyśrodkowanym tekstem i przejść do następnego wiersza, wykonalibyśmy:

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

Uwaga: łamanie wiersza można również wykonać za pomocą ln. Ta metoda pozwala dodatkowo określić wysokość przerwy.

Na koniec dokument jest zamykany i zapisywany pod podaną ścieżką pliku za pomocą output. Bez podanego parametru output() zwraca bufor PDF bytearray.

Tuto 2 - Nagłówek, stopka, podział strony i obraz

Oto przykład dwustronicowy z nagłówkiem, stopką i 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")

Plik wynikowy PDF

Ten przykład wykorzystuje metody header i footer do przetwarzania nagłówków i stopek stron. Są one wywoływane automatycznie. Istnieją już w klasie FPDF, ale nic nie robią, dlatego musimy rozszerzyć klasę i je nadpisać.

Logo jest drukowane za pomocą metody image, która określa jego górny lewy róg i szerokość. Wysokość jest automatycznie obliczana, aby zachować proporcje obrazu.

Aby wydrukować numer strony, jako szerokość komórki przekazywana jest wartość null. Oznacza to, że komórka powinna rozciągać się do prawego marginesu strony; jest to przydatne do centrowania tekstu. Bieżący numer strony zwracany jest przez metodę page_no; Całkowita liczba stron jest uzyskiwana za pomocą specjalnej wartości {nb}, która zostanie zastąpiona przy zamykaniu dokumentu (tę wartość specjalną można zmienić za pomocą metody
alias_nb_pages()). Należy zwrócić uwagę na użycie metody set_y, która pozwala ustawić pozycję w dowolnym miejscu na stronie, zaczynając od góry lub od dołu.

Kolejną interesującą funkcją stosowaną tutaj jest automatyczne łamanie strony. Gdy tylko komórka przekroczy limit strony (domyślnie 2 centymetry od dołu), następuje łamanie i przywrócenie czcionki. Chociaż nagłówek i stopka wybierają własną czcionkę (helvetica), treść dokumentu jest kontynuowana czcionką Times. Ten mechanizm automatycznego przywracania dotyczy również kolorów i grubości linii. Limit wywołujący łamanie strony można ustawić za pomocą metody set_auto_page_break.

Tuto 3 - Łamanie wierszy i kolory

Kontynuujmy przykładem drukowania wyjustowanych akapitów. Ilustruje on również zastosowanie kolorów.

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")

Plik wynikowy PDF

Jules Verne text

Metoda get_string_width pozwala określić długość łańcucha znaków w bieżącej czcionce. Używana jest tutaj do obliczenia pozycji i szerokości ramki otaczającej tytuł. Następnie ustawiane są kolory (za pomocą metod set_draw_color, set_fill_color i set_text_color) oraz grubość linii na 1 mm (domyślnie jest to 0,2 mm) za pomocą metody set_line_width. Na koniec wyprowadzana jest komórka (ostatni parametr ustawiony na true oznacza, że tło musi być wypełnione).

Metodą używaną do drukowania akapitów jest multi_cell. Text is justified by default. Domyślnie tekst jest wyjustowany. Za każdym razem, gdy linia osiąga prawy koniec komórki lub napotkany zostanie znak nowej linii (\n), następuje łamanie wiersza i automatyczne utworzenie nowej komórki pod bieżącą. Automatyczne łamanie wiersza następuje w miejscu najbliższej spacji lub miękkiego łącznika (\u00ad) przed prawą krawędzią. Miękki łącznik zostanie zastąpiony zwykłym łącznikiem podczas łamania wiersza, a w przeciwnym razie zostanie zignorowany.

W dokumencie definiowane są dwie właściwości: tytuł (set_title) i autor (set_author). Właściwości można wyświetlić na dwa sposoby. Pierwszy to bezpośrednie otwarcie dokumentu w programie Acrobat Reader, przejście do menu Plik i wybranie opcji Właściwości dokumentu. Drugi sposób, również dostępny z wtyczki, polega na kliknięciu prawym przyciskiem myszy i wybraniu opcji Właściwości dokumentu.

Tuto 4 - Wiele kolumn

Ten przykład jest wariantem poprzedniego, pokazującym jak rozłożyć tekst na wiele kolumn.

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")

Plik wynikowy PDF

Jules Verne text

Główna różnica w stosunku do poprzedniego tutoriala polega na użyciu metody text_columns. Gromadzi ona cały tekst, możliwie w częściach, i rozdziela go na żądaną liczbę kolumn, automatycznie wstawiając łamanie strony w razie potrzeby. Należy zauważyć, że dopóki instancja TextColumns jest aktywna jako menedżer kontekstu, style tekstu i inne właściwości czcionki można zmieniać. Zmiany te będą ograniczone do kontekstu. Po jego zamknięciu zostaną przywrócone poprzednie ustawienia.

Tuto 5 - Tworzenie tabel

W tym tutorialu omówione zostanie tworzenie dwóch różnych tabel, aby pokazać, co można osiągnąć za pomocą prostych modyfikacji.

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")

Plik wynikowy PDF - Dane CSV z krajami

Pierwszy przykład przedstawia najprostszy sposób przekazania danych do funkcji FPDF.table(). Wynik jest podstawowy, ale bardzo szybki do uzyskania.

Druga tabela zawiera pewne ulepszenia: kolory, ograniczona szerokość tabeli, zmniejszona wysokość linii, wyśrodkowane tytuły, kolumny o niestandardowych szerokościach, wyrównane do prawej cyfry... Ponadto usunięto linie poziome. Zrealizowano to poprzez wybranie borders_layout spośród dostępnych wartości: TableBordersLayout.

Tuto 6 - Tworzenie linków i mieszanie stylów tekstu

W tym samouczku omówione zostaną różne sposoby wstawiania łączy w dokumencie PDF, a także dodawania łączy do źródeł zewnętrznych.

Pokaże również kilka sposobów, w jakie możemy używać różnych stylów tekstu, (pogrubienie, kursywa, podkreślenie) w ramach tego samego tekstu.

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")

Plik wynikowy PDF - fpdf2-logo

Nowa metoda drukowania tekstu pokazana tutaj to write() . Jest bardzo podobna do multi_cell() , przy czym główne różnice polegają na:

  • Koniec linii znajduje się na prawym marginesie, a następny wiersz zaczyna się na lewym marginesie.
  • TAktualna pozycja przesuwa się do końca tekstu.

Dlatego metoda pozwala nam napisać fragment tekstu, zmienić styl czcionki i kontynuować dokładnie od miejsca, w którym skończyliśmy. Z drugiej strony, jej główną wadą jest to, że nie możemy wyjustować tekstu tak jak robimy to za pomocą metody multi_cell() .

W pierwszej stronie przykładu użyliśmy do tego celu metody write() Początek zdania zapisany jest zwykłą czcionką, następnie za pomocą metody set_font() przełączyliśmy się na podkreślenie i dokończyliśmy zdanie.

Aby dodać link wewnętrzny prowadzący do drugiej strony, użyliśmy metody add_link() , która tworzy klikalny obszar nazwany przez nas "link", który kieruje do innej strony w dokumencie.

Do utworzenia linku zewnętrznego za pomocą obrazu użyliśmy metody image() . Metoda ta ma opcję przekazania linku jako jednego z argumentów. Link może być zarówno wewnętrzny, jak i zewnętrzny.

Alternatywnie, inną opcją zmiany stylu czcionki i dodawania linków jest użycie metody z write_html(). Jest to parser html, który pozwala na dodawanie tekstu, zmianę stylu czcionki i dodawanie linków za pomocą html.