Skip to content

Πρόγραμμα Εκμάθησης

Πλήρης τεκμηρίωση των μεθόδων: fpdf.FPDF API doc

Μάθημα 1 - Απλό Παράδειγμα

Ας ξεκινήσουμε με ένα κλασσικό παράδειγμα:

from fpdf import FPDF

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

Παραγόμενο PDF

Αφού συμπεριλάβουμε το αρχείο βιβλιοθήκης, δημιουργούμε ένα αντικείμενο FPDF. Ο κατασκευαστής FPDF χρησιμοποιείται στην προκειμένη περίπτωση με τις προκαθορισμένες τιμές: οι σελίδες έχουν διαστάσεις Α4 και η μονάδας μέτρησης είναι το χιλιοστόμετρο. Οι συγκεκριμένες τιμές μπορούν να προσδιοριστούν αναλυτικά ως εξής:

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

Δίνεται η δυνατότητα να ορίσουμε το PDF σε λειτουργία τοπίου (L) ή να χρησιμοποιήσουμε άλλες μορφοποιήσεις σελίδας (όπως Letter και Legal) και μονάδες μέτρησης (pt, cm, in).

Προς το παρόν δεν υπάρχει σελίδα, οπότε θα προσθέσουμε μία με την μέθοδο add_page. Η αρχή βρίσκεται στην αριστερή άνω γωνία και η τρέχουσα θέση τοποθετείται, από προεπιλογή, σε απόσταση 1 cm από το περίγραμμα. Τα περιθώρια μπορούν να οριστούν με set_margins.

Πρωτού μπορέσουμε να εκτυπώσουμε κείμενο, είναι υποχρεωτικό να επιλέξουμε γραμματοσειρά με set_font, αλλιώς το αρχείο δεν θα είναι έγκυρο. Επιλέγουμε τη γραμματοσειρά Helvetica bold 16:

pdf.set_font('Helvetica', style='B', size=16)

Μπορούμε να επιλέξουμε πλάγια γραφή με I, υπογράμμιση με U η μία απλή γραμματοσειρά με μία κενή συμβολοσειρά (ή οποιονδήποτε συνδιασμό). Αξίζει να σημειωθεί ότι το μέγεθος της γραμματοσειράς δίνεται σε σημεία, όχι χιλιοστόμετρα (ή κάποια άλλη μονάδα μέτρησης). Το παραπάνω αποτελεί τη μοναδική εξαίρεση. Οι υπόλοιπες ενσωματωμένες γραμματοσείρες είναι Times, Courier, Symbol and ZapfDingbats.

Πλέον, μπορούμε να εκτυπώσουμε ένα κελί cell. Ένα κελί αποτελεί μία ορθογώνια επιφάνεια, πιθανώς πλαισιωμένη, η οποία περιέχει κείμενο. Απεικονίζεται στην τρέχουσα θέση. Ορίζουμε τις διαστάσεις της, το κείμενό της (κεντραρισμένο ή ευθυγραμμισμένο), εάν επιθυμούμε εμφάνιση του περιγράμματος, και που θα μετακινηθεί η τρέχουσα θέση μετά από αυτή (στα δεξιά της ορθογώνιας επιφάνειας, από κάτω της ή στην αφετηρία της επόμενης γραμμής). Μπορούμε να προσθέσουμε ένα πλαίσιο ως εξής:

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

Για να προσθέσουμε ένα νέο κελί δίπλα στο αρχικό με κεντραρισμένο κείμενο και στη συνέχεια να μεταβούμε στην επόμενη γραμμή, χρησιμοποιούμε:

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

Παρατήρηση: η αλλαγή γραμμής μπορεί να πραγματοποιηθεί και με ln. Αυτή η μέθοδος επιτρέπει επίσης τον προσδιορισμό του ύψους της αλλαγής γραμμής.

Εν τέλει, το αρχείο μας είναι κλειστό και έχει αποθηκευτεί στην παρεχόμενη διαδρομή αρχείου χρησιμοποιώντας output. Αν δεν παρέχουμε παραμέτρους, η μέθοδος output() επιστρέφει το αρχείο PDF σε μορφή bytearray.

Μάθημα 2 - Επικεφαλίδα, υποσέλιδο, αλλαγή σελίδας και εικόνα

Παρακάτω, παρουσιάζεται ένα παράδειγμα με τη χρήση επικεφαλίδας, υποσέλιδου και λογότυπου:

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", style="B", size=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", style="I", size=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")

Παραγόμενο PDF

Στο συγκεκριμένο παράδειγμα γίνεται χρήση των μεθόδων header και footer έτσι ώστε να επεξεργαστούμε τις επικεφαλίδες και τα υποσέλιδα των σελίδων ενός αρχείου. Η κλήση τους γίνεται αυτόματα. Υπάρχουν ήδη στην κλάση FPDF αλλά δεν προσφέρουν καμία λειτουργία, επομένως χρειάζεται να επεκτείνουμε την κλάση και να τις υπερκαλύψουμε.

Το λογότυπο εκτυπώνεται με την μέθοδο image διευκρινίζοντας την αριστερή άνω γωνία και το πλάτος του. Το ύψος της υπολογίζεται αυτόματα λαμβάνοντας υπόψη τις αναλογίες της εικόνας.

Για να εκτυπώσουμε τον αριθμό της σελίδας, χρειάζεται να περάσουμε την μηδενική τιμή στην παράμετρο του πλάτους κελιού. Αυτό σημαίνει ότι το κελί θα επεκταθεί μέχρι και το δεξί περιθώριο της σελίδας, το οποίο βολεύει στο κεντράρισμα του κειμένου. Ο αριθμός της τωρινής σελίδας παρέχεται από την μέθοδο page_no. Ο συνολικός αριθμός σελίδων του κειμένου είναι διαθέσιμος μέσω της ειδικής μεταβλητής {nb}, η οποία ορίζεται με το κλείσιμο του αρχείου. Αυτή η ειδική τιμή μπορεί να τροποποιηθεί μέσω της μεθόδου alias_nb_pages(). Αξίζει να σημειωθεί ότι η μέθοδος set_y επιτρέπει τον ορισμό της τρέχουσας θέσης σε οποιαδήποτε τοποθεσία στη σελίδα, ξεκινώντας από την κορυφή ή το τέλος της σελίδας.

Ένα ακόμη ενδιαφέρον χαρακτηριστικό παρουσιάζεται στην συγκεκριμένη περίπτωση: η αυτόματη αλλαγή σελίδας. Μόλις ένα κελί ξεπεράσει ένα προκαθορισμένο όριο στη σελίδα (2 εκατοστά από το κάτω μέρος της σελίδας εξ ορισμού), πραγματοποιείται αλλαγή γραμμής και η γραμματοσειρά επαναφέρεται. Παρόλο που η επικεφαλίδα και το υποσέλιδο επιλέγουν την δικιά τους γραμματοσειρά (helvetica), το κύριο τμήμα του κειμένου συνεχίζει με τη γραμματοσειρά Times. Αυτός ο μηχανισμός της αυτόματης επαναφοράς εφαρμόζεται επιπλέον στο χρώμα και στο πλάτος γραμμής. Το όριο που προκαλεί την αλλαγή σελίδας μπορεί να οριστεί μέσω της μεθόδου set_auto_page_break.

Μάθημα 3 - Αλλαγές γραμμής και χρώματα

Ας συνεχίσουμε με ένα παράδειγμα το οποίο εκτυπώνει ευθυγραμμισμένες παραγράφους. Επίσης επεξηγεί τη χρήση χρωμάτων.

from fpdf import FPDF


class PDF(FPDF):
    def header(self):
        # Setting font: helvetica bold 15
        self.set_font("helvetica", style="B", size=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", style="I", size=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", size=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")

Παραγόμενο PDF

Κείμενο του Jules Verne

Η μέθοδος get_string_width επιτρέπει τον καθορισμό του μήκους μίας συμβολοσειράς στην τωρινή γραμματοσειρά, το οποίο χρησιμοποιείται στη συγκεκριμένη περίπτωση για τον υπολογισμό της θέσης και του πλάτους του πλαισίου που περιβάλλει τον τίτλο. Έπειτα ορίζονται τα χρώματα (μέσω set_draw_color, set_fill_color και set_text_color) και το πάχος της γραμμής ορίζεται ως 1 χιλιοστόμετρο (αντιθέτως της προκαθορισμένης τιμής 0.2) μέσω της μεθόδου set_line_width. Τελικά, εκτυπώνουμε το κελί (η τελευταία παράμετρος ίση με true υποδηλώνει την κάλυψη του υπόβαθρου).

Για την εκτύπωση των παραγράφων χρησιμοποιήσαμε την μέθοδο multi_cell. Το κείμενο ευθυγραμμίζεται αυτόματα. Κάθε φορά που μία γραμμή φτάνει στην ακραία δεξιά θέση του κελιού ή συναντάται χαρακτήρας επιστροφής φορέα (\n), καλείται αλλαγή γραμμής και ένα νέο κελί δημιουργείται αυτόματα κάτω από το τωρινό. Μία αυτόματη αλλαγή γραμμής πραγματοποιείται στο σημείο με το πλησιέστερο χαρακτήρα κενού ή ενωτικού συλλαβής (\u00ad) πριν την ακραία δεξιά θέση. Ένα ενωτικό συλλαβής θα αντικατασταθεί από ένα απλό ενωτικό όταν πραγματοποιείται αλλαγή γραμμής, αλλιώς θα αγνοηθεί.

Ορίζονται δύο ιδιότητες αρχείου: ο τίτλος (set_title) και ο συγγραφέας (set_author). Οι ιδιότητες μπορούν να προβληθούν με δύο τρόπους. Πρώτον, μπορούμε να ανοίξουμε το αρχείο απευθείας μέσω Acrobat Reader, να κατευθυνθούμε στο Μενού Αρχείων και να επιλέξουμε την επιλογή Ιδιότητες Αρχείου. Δεύτερον, μπορούμε απευθείας να κάνουμε δεξί κλικ στο εικονίδιο αρχείου και να επιλέξουμε τις Ιδιότητες Αρχείου.

Μάθημα 4 - Πολλαπλές Στήλες

Αυτό το παράδειγμα αποτελεί μία παραλλαγή του προηγούμενου και μας παρουσιάζει πως να κατανέμουμε το κείμενό μας σε πολλαπλές στήλες.

from fpdf import FPDF


class PDF(FPDF):
    def header(self):
        self.set_font("helvetica", style="B", size=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", style="I", size=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", size=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")

Παραγόμενο PDF

Κείμενο του Jules Verne

⚠️ This section has changed a lot and requires a new translation: https://github.com/py-pdf/fpdf2/issues/267

English versions:

Μάθημα 5 - Δημιουργία Πινάκων

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

Παραγόμενο PDF - Κείμενο Χωρών

⚠️ This section has changed a lot and requires a new translation: https://github.com/py-pdf/fpdf2/issues/267

English versions:

Μάθημα 6 - Δημιουργία συνδέσμων και μίξη στυλ κειμένου

Σε αυτό το μάθημα θα εξηγήσουμε πολλαπλούς τρόπους εισαγωγής εσωτερικών αλλα και εξωτερικών συνδέσμων σε ένα αρχείο pdf.

Θα αναλύσουμε επίσης πως μπορούμε να χρησιμοποιήσουμε διάφορα στυλ κειμένου (έντονη γραφή, πλάγια γραφή, υπογράμμιση) εντός του ίδιου κειμένου.

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

Παραγόμενο PDF - fpdf2-logo

Παρατηρούμε μία νέα μέθοδο για την εκτύπωση κειμένου, την write() . Η μέθοδος αυτή, θυμίζει αρκετά την multi_cell() , παρόλα αυτά εμφανίζει τις εξής διαφορές:

  • Το τέλος της γραμμής βρίσκεται στο δεξί περιθώριο και η επόμενη γραμμή ξεκινάει στο αριστερό περιθώριο.
  • Η τρέχουσα θέση μετακινείται στο τέλος του κειμένου.

Αυτή η μέθοδος, επομένως μας επιτρέπει να γράψουμε ένα κομμάτι κειμένου, να αλλάξουμε τη γραμματοσειρά, και να συνεχίσουμε ακριβώς στο σημείο που είχαμε απομείνει. Από την άλλη πλευρά, το βασικό της μειονέκτημα είναι ότι δεν μπορούμε να ευθυγραμμίσουμε το κείμενο όπως με την μέθοδο multi_cell().

Στην πρώτη σελίδα του παραδείγματος χρησιμοποιήσαμε την μέθοδο write() για αυτό το σκοπό. Το πρώτο κομμάτι της πρότασης είναι γραμμένο ως απλό κείμενο, ενώ στη συνέχεια, αφού χρησιμοποιήσαμε την μέθοδο set_font(), αλλάξαμε το στυλ κειμένου σε υπογράμμιση και κλείσαμε την πρόταση.

Για να προσθέσουμε έναν εσωτερικό σύνδεσμο ο οποίος θα κατευθύνει στην επόμενη σελίδα, χρησιμοποιήσαμε την μέθοδο add_link(), η οποία δημιουργεί μία επιφανεία με όνομα "link". Αν κλικάρουμε την επιφάνεια αυτή μεταφερόμαστε σε μία άλλη τοποθεσία του αρχείου.

Για να δημιουργήσουμε έναν εξωτερικό σύνδεσμο μέσω μιας εικόνας, θα χρησιμοποιήσουμε την μέθοδο image(). Αυτή η μέθοδος μας δίνει την επιλογή να περάσουμε έναν σύνδεσμο ως τιμή σε μία από τις παραμέτρους της. Ο σύνδεσμος μπορεί να είναι εσωτερικός ή εξωτερικός.

Εναλλακτικά, μία ακόμη επιλογή για να αλλάξουμε το στυλ κειμένου και να προσθέσουμε συνδέσμους είναι η χρήση της μεθόδου write_html(). Η μέθοδος αυτή, αποτελεί έναν αναλυτή html ο οποίος επιτρέπει την προσθήκη κειμένου, την αλλαγή γραμματοσειράς και την προσθήκη συνδέσμων με την χρήση της html.