Руководство¶
Полная документация по методам класса FPDF: fpdf.FPDF
API doc
Руководство 1 - Минимальный пример¶
Начнём с классического примера:
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")
После подключения библиотеки мы создаем объект FPDF
. Здесь используется конструктор FPDF со значениями по умолчанию: страницы формата A4 портретные, единица измерения - миллиметр.
pdf = FPDF(orientation="P", unit="mm", format="A4")
Можно установить PDF в альбомном режиме (L
) или использовать другой формат страниц (например, Letter
или Legal
) и единицы измерения (pt
, cm
, in
).
На данный момент страницы нет, поэтому мы должны добавить ее с помощью команды add_page. Начало страницы находится в левом верхнем углу, а текущая позиция по умолчанию располагается на расстоянии 1 см от границ; поля можно изменить с помощью команды set_margins.
Прежде чем мы сможем напечатать текст, обязательно нужно выбрать шрифт с помощью set_font, иначе документ будет недействительным. Мы выбираем Helvetica bold 16:
pdf.set_font('helvetica', 'B', 16)
Мы можем указать курсив с помощью I
, подчеркнутый шрифт с помощью U
или обычный шрифт с помощью пустой строки (или использовать любую комбинацию). Обратите внимание, что размер шрифта задается в пунктах, а не в миллиметрах (или другой единице измерений); это единственное исключение. Другие встроенные шрифты: Times
, Courier
, Symbol
и 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", "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")
В этом примере используются методы header и footer для обработки заголовков и колонтитулов страницы. Они вызываются автоматически. Они уже существуют в классе FPDF, но ничего не делают, поэтому мы должны расширить класс и переопределить их.
Логотип печатается методом image с указанием его левого верхнего угла и ширины. Высота вычисляется автоматически, чтобы соблюсти пропорции изображения.
Для печати номера страницы в качестве ширины ячейки передается нулевое значение. Это означает, что ячейка должна простираться до правого поля страницы; это удобно для центрирования текста. Номер текущей страницы возвращается методом page_no; что касается общего количества страниц, то оно получается с помощью специального значения {nb}
, которое будет подставлено при закрытии документа. Обратите внимание на использование метода 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", "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")
Метод get_string_width позволяет определить длину строки в текущем шрифте, которая используется здесь для расчета положения и ширины рамки, окружающей заголовок. Затем устанавливаются цвета (через set_draw_color, set_fill_color и set_text_color), а толщина линии устанавливается в 1 мм (против 0,2 по умолчанию) с помощью set_line_width. Наконец, мы выводим ячейку (последний параметр True указывает на то, что фон должен быть заполнен).
Для печати абзацев используется метод multi_cell. Каждый раз, когда строка достигает правого края ячейки или встречается символ возврата каретки, выдается разрыв строки и автоматически создается новая ячейка под текущей. По умолчанию текст выравнивается по ширине.
Определены два свойства документа: заголовок (set_title) и автор (set_author). Свойства можно просматривать двумя способами. Первый - открыть документ непосредственно с помощью Acrobat Reader, перейти в меню Файл и выбрать пункт Свойства документа. Второй, также доступный из плагина, - щелкнуть правой кнопкой мыши и выбрать пункт Свойства документа.
Руководство 4 - Несколько колонок¶
Этот пример является вариантом предыдущего и показывает, как расположить текст в нескольких колонках.
from fpdf import FPDF
class PDF(FPDF):
def __init__(self):
super().__init__()
self.col = 0 # Current column
self.y0 = 0 # Ordinate of column start
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)
# Saving ordinate position:
self.y0 = self.get_y()
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 set_col(self, col):
# Set column position:
self.col = col
x = 10 + col * 65
self.set_left_margin(x)
self.set_x(x)
@property
def accept_page_break(self):
if self.col < 2:
# Go to next column:
self.set_col(self.col + 1)
# Set ordinate to top:
self.set_y(self.y0)
# Stay on the same page:
return False
# Go back to first column:
self.set_col(0)
# Trigger a page break:
return True
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)
# Saving ordinate position:
self.y0 = self.get_y()
def chapter_body(self, name):
# Reading text file:
with open(name, "rb") as fh:
txt = fh.read().decode("latin-1")
# Setting font: Times 12
self.set_font("Times", size=12)
# Printing text in a 6cm width column:
self.multi_cell(60, 5, txt)
self.ln()
# Final mention in italics:
self.set_font(style="I")
self.cell(0, 5, "(end of excerpt)")
# Start back at first column:
self.set_col(0)
def print_chapter(self, num, title, name):
self.add_page()
self.chapter_title(num, title)
self.chapter_body(name)
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")
Ключевым отличием от предыдущего урока является использование методов accept_page_break и set_col.
С помощью метода accept_page_break, в тот момент, когда ячейка пересекает нижнюю границу страницы, проверяется номер текущей колонки. Если он меньше 2 (мы решили разделить страницу на три колонки), то будет вызван метод set_col, увеличивающий номер колонки и изменяющий положение следующей колонки, чтобы текст мог быть продолжен в ней.
Как только будет достигнута нижняя граница третьей колонки, метод accept_page_break произведет сброс и возврат к первой колонке и инициирует разрыв страницы.
Руковдство 5 - Создание таблиц¶
В этом уроке мы расскажем, как можно с легкостью создавать таблицы.
Код создаст три различные таблицы, чтобы объяснить, чего можно достичь с помощью нескольких простых настроек.
import csv
from fpdf import FPDF
class PDF(FPDF):
def basic_table(self, headings, rows):
for heading in headings:
self.cell(40, 7, heading, 1)
self.ln()
for row in rows:
for col in row:
self.cell(40, 6, col, 1)
self.ln()
def improved_table(self, headings, rows, col_widths=(42, 39, 35, 40)):
for col_width, heading in zip(col_widths, headings):
self.cell(col_width, 7, heading, border=1, align="C")
self.ln()
for row in rows:
self.cell(col_widths[0], 6, row[0], border="LR")
self.cell(col_widths[1], 6, row[1], border="LR")
self.cell(col_widths[2], 6, row[2], border="LR", align="R")
self.cell(col_widths[3], 6, row[3], border="LR", align="R")
self.ln()
# Closure line:
self.cell(sum(col_widths), 0, "", border="T")
def colored_table(self, headings, rows, col_widths=(42, 39, 35, 42)):
# Colors, line width and bold font:
self.set_fill_color(255, 100, 0)
self.set_text_color(255)
self.set_draw_color(255, 0, 0)
self.set_line_width(0.3)
self.set_font(style="B")
for col_width, heading in zip(col_widths, headings):
self.cell(col_width, 7, heading, border=1, align="C", fill=True)
self.ln()
# Color and font restoration:
self.set_fill_color(224, 235, 255)
self.set_text_color(0)
self.set_font()
fill = False
for row in rows:
self.cell(col_widths[0], 6, row[0], border="LR", align="L", fill=fill)
self.cell(col_widths[1], 6, row[1], border="LR", align="L", fill=fill)
self.cell(col_widths[2], 6, row[2], border="LR", align="R", fill=fill)
self.cell(col_widths[3], 6, row[3], border="LR", align="R", fill=fill)
self.ln()
fill = not fill
self.cell(sum(col_widths), 0, "", "T")
def load_data_from_csv(csv_filepath):
headings, rows = [], []
with open(csv_filepath, encoding="utf8") as csv_file:
for row in csv.reader(csv_file, delimiter=","):
if not headings: # extracting column names from first row:
headings = row
else:
rows.append(row)
return headings, rows
col_names, data = load_data_from_csv("countries.txt")
pdf = PDF()
pdf.set_font("helvetica", size=14)
pdf.add_page()
pdf.basic_table(col_names, data)
pdf.add_page()
pdf.improved_table(col_names, data)
pdf.add_page()
pdf.colored_table(col_names, data)
pdf.output("tuto5.pdf")
Поскольку таблица - это просто набор ячеек, естественно построить таблицу из них.
Первый пример достигается самым простым способом: простые ячейки в рамке, все одинакового размера и выровненные по левому краю. Результат элементарен, но достигается очень быстро.
Вторая таблица имеет некоторые улучшения: каждый столбец имеет свою ширину, заголовки выровнены по центру, а цифры - по правому краю. Более того, горизонтальные линии были удалены. Это сделано с помощью параметра border метода Cell(), который указывает, какие стороны ячейки должны быть нарисованы. Здесь нам нужны левая (L) и правая (R). Теперь остается только проблема горизонтальной линии для завершения таблицы. Есть две возможности решить ее: проверить наличие последней строки в цикле, в этом случае мы используем LRB для параметра границы; или, как сделано здесь, добавить линию после завершения цикла.
Третья таблица похожа на вторую, но в ней используются цвета. Цвета заливки, текста и линий просто задаются. Альтернативная окраска строк достигается путем использования поочередно прозрачных и заполненных ячеек.
Руководство 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://pyfpdf.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://pyfpdf.github.io/fpdf2/">https://pyfpdf.github.io/fpdf2/</a>,
or on an image: the logo is clickable!"""
)
pdf.output("tuto6.pdf")
Новый метод, показанный здесь для печати текста - это write(). Он очень похож на multi_cell(), основные отличия заключаются в следующем:
- Конец строки находится на правом поле, а следующая строка начинается на левом поле.
- Текущая позиция перемещается в конец текста.
Таким образом, этот метод позволяет нам написать фрагмент текста, изменить стиль шрифта и продолжить с того самого места, на котором мы остановились. С другой стороны, его главный недостаток заключается в том, что мы не можем выровнять текст, как это делается при использовании метода multi_cell().
На первой странице примера мы использовали для этой цели write(). Начало предложения написано текстом обычного стиля, затем, используя метод set_font(), мы переключились на подчеркивание и закончили предложение.
Для добавления внутренней ссылки, указывающей на вторую страницу, мы использовали метод add_link(), который создает кликабельную область, названную нами "link", которая ведет в другое место внутри документа.
Чтобы создать внешнюю ссылку с помощью изображения, мы использовали метод image(). Этот метод имеет возможность передать ссылку в качестве одного из аргументов. Ссылка может быть как внутренней, так и внешней.
В качестве альтернативы для изменения стиля шрифта и добавления ссылок можно использовать метод write_html()
. Это парсер html, который позволяет добавлять текст, изменять стиль шрифта и добавлять ссылки с помощью html.