Сравнение способов генерации pdf из html. Создаем документ PDF из PHP скрипта с помощью библиотеки FPDF Добавляем линии осей и метки на них

  • 22.04.2024

Теперь можно добавить название отчета. Объект FPDF использует концепцию "текущая позиция", куда вставляется следующая часть текста или другой элемент. Так как нужно, чтобы название отчета располагалось в середине страницы, необходимо передвинуть текущую позицию вниз к данной точке, которая располагается на расстоянии 160мм от верха страницы (значение хранится в конфигурационной переменной $reportNameYPos). Для этого используется метод FPDF Ln() , который добавляет перевод строки на указанное расстояние:

$pdf->Ln($reportNameYPos);

Если не указать высоту перевода строки, то будет использоваться высота последней выведенной ячейки.

Теперь добавим название отчета. Существует несколько различных способов добавить текст с помощью FPDF. В нашем случае используем метод Cell() , который, помимо всего прочего, позволяет легко центрировать текст.

Cell() принимает следующие аргументы (все являются опциональными):

  • Высота и ширина ячейки. По умолчанию ширина растягивается до правого поля, а высота устанавливается в 0.
  • Строка текста для вывода. По умолчанию "" .
  • Указание для отображения рамки вокруг ячейки. Это может быть либо число (0 =нет рамки, 1 =рисуем рамку), или строка с одним или несколькими параметрами из следующего списка: "L" (слева), "T" (сверху), "R" (справа), и "B" (внизу). Значение по умолчанию: 0 .
  • Куда помещать текущую позицию после вывода ячейки. Значение может быть 0 (справа от ячейки), 1 (начало следующей строки), или 2 (ниже). Значение по умолчанию: 0 .
  • Выравнивание текста . Возможные значения: "L" (выравнивание по левому краю), "C" (выравнивание по центру), или "R" (выравнивание по правому краю). Значение по умолчанию: "L" .
  • Нужно ли заливать фон ячейки цветом. true = заливаем цветом, false = оставляем фон прозрачным. Значение по умолчанию: false .
  • URL ссылки. Если задан, то ячейка с текстом становится рабочей ссылкой на другой ресурс.

Теперь с помощью метода Cell() вставим название отчета и выровняем его по центру:

$pdf->

Создаем колонтитул страницы и вводный текст

Итак, титульная страница готова. Теперь надо создать страницу, на которой есть колонтитул, заголовок и некоторый вводный текст, за которым следует таблица и график.

Сделаем колонтитул страницы. Добавим новую страницу, затем выведем текст колонтитула, который содержит название отчета, выровнен по центру страницы и использует шрифт Arial размером 17. Используем переменную конфигурации $headerColour для установки цвета текста:

$pdf->AddPage(); $pdf->SetTextColor($headerColour, $headerColour, $headerColour); $pdf->SetFont("Arial", "", 17); $pdf->Cell(0, 15, $reportName, 0, 0, "C");

Теперь перейдем к тексту. Сначала выведем заголовок в обычном цвете и шрифтом Arial размером 20. Так как нам не нужно центрировать текст, можно использовать простой метод Write() , передав ему высоту строки и текст для вывода (в качестве опции можно также передать адрес URL для формирования ссылки):

$pdf->SetTextColor($textColour, $textColour, $textColour); $pdf->SetFont("Arial", "", 20); $pdf->Write(19, "2009 Was A Good Year");

Теперь можно вывести текст введения шрифтом Arial размером 12. Здесь есть пропуски 16 мм от первого абзаца и 12 мм между параграфами. Задаем для каждой строки высоту в 6 мм:

$pdf->Ln(16); $pdf->SetFont("Arial", "", 12); $pdf->Write(6, "Despite the economic downturn, WidgetCo had a strong year. Sales of the HyperWidget in particular exceeded expectations. The fourth quarter was generally the best performing; this was most likely due to our increased ad spend in Q3."); $pdf->Ln(12); $pdf->Write(6, "2010 is expected to see increased sales growth as we expand into other countries.");

Метод Write() автоматически переводит текст на следующую строку, когда он достигает правой стороны страницы.

Добавляем данные

Теперь нужно добавить таблицу с данными ниже текста. сначала установим цвет рамки таблицы. Метод SetDrawColor() устанавливает цвет, который используется для рамок и других линий, так что мы можем использовать его для установки цвета для рамок ячеек таблицы. Затем текущую позицию опускаем вниз на 15мм для создания пробела между текстом и таблицей:

$pdf->SetDrawColor($tableBorderColour, $tableBorderColour, $tableBorderColour); $pdf->Ln(15);

Создаем строку заголовков таблицы

Таблица имеет строку, которая содержит в ячейках заголовки столбцов "PRODUCT", "Q1, "Q2", "Q3", и "Q4". Ячейка "PRODUCT" использует отличный от других заголовков цвет текста и фона.

Мы уже пользовались методом SetTextColor() для установки цвета текста. Для установки цвета фона надо использовать метод SetFillColor() , который имеет такие же аргументы как SetTextColor() .

Чтобы создать ячейки таблицы используется метод Cell() , которому задаются ширина и высота ячейки, содержание и выравнивание. Также передается 1 в качестве 4-го аргумента для установки рамки, и true в качестве 7-го аргумента для заполнения фона установленным цветом.

Ниже приведен код для создания строки заголовков. Сначала устанавливается полужирный шрифт. Затем создается ячейка "PRODUCT" с соответствующим текстом и фоном. Затем устанавливается цвет для оставшихся 4 ячеек заголовков, и выполняется цикл по элементам массива $columnLabels для вывода ячеек с выравниванием текста в них по центру:

// Создаем строку заголовков таблицы $pdf->SetFont("Arial", "B", 15); // Ячейка "PRODUCT" $pdf->SetTextColor($tableHeaderTopProductTextColour, $tableHeaderTopProductTextColour, $tableHeaderTopProductText Colour); $pdf->SetFillColor($tableHeaderTopProductFillColour, $tableHeaderTopProductFillColour, $tableHeaderTopProductFill Colour); $pdf->Cell(46, 12, " PRODUCT", 1, 0, "L", true); // Остальные ячейки заголовков $pdf->SetTextColor($tableHeaderTopTextColour, $tableHeaderTopTextColour, $tableHeaderTopTextColour); $pdf->SetFillColor($tableHeaderTopFillColour, $tableHeaderTopFillColour, $tableHeaderTopFillColour); for ($i=0; $iCell(36, 12, $columnLabels[$i], 1, 0, "C", true); } $pdf->Ln(12);

Пробел в начале содержимого ячейки "PRODUCT" помогает сформировать отступ в ячейке таблицы от левой границы. Такой же трюк будет использоваться для наименований продуктов в крайнем левом столбце (к сожалению, пока нет способа контролировать отступ в ячейках с помощью FPDF).

Создаем строки с данными

Остальная таблица состоит из 4 строк с данными продаж (по одной строке на продукт) для 4-х кварталов. Сначала определим пару переменных:

// Создаем строки с данными $fill = false; $row = 0;

Переменные служат для:

    $fill: Заполнять фон ячейки цветом или нет. Мы будем переключать данное значение после вывода каждой строки для получения эффекта зебры в таблице.

    $row: Текущий номер строки. Она позволяет выводить соответствующий номер для каждой строки при перемещении по таблице.

Теперь можно организовать цикл по элементам массива $data с помощью foreach для вывода строк Для каждой строки создаем левую ячейку, которая содержит название продукта, и четыре ячейки с данными. Устанавливаем соответствующие цвета для тескта и фона для каждой ячейки.

Для вывода ячеек данных используется цикл for для прохода по четырех элементному массиву с данными, а для вывода данных в формате с разделением тысяч вызываем функцию PHP number_format() .

После вывода строки увеличиваем переменную $row , переключаем переменную $fill , и используем Ln() для перехода к началу следующей строки.

Вот код всего цикла:

Foreach ($data as $dataRow) { // Создаем левую ячейку с заголовком строки $pdf->SetFont("Arial", "B", 15); $pdf->SetTextColor($tableHeaderLeftTextColour, $tableHeaderLeftTextColour, $tableHeaderLeftTextColour); $pdf->SetFillColor($tableHeaderLeftFillColour, $tableHeaderLeftFillColour, $tableHeaderLeftFillColour); $pdf->Cell(46, 12, " " . $rowLabels[$row], 1, 0, "L", $fill); // Создаем ячейки с данными $pdf->SetTextColor($textColour, $textColour, $textColour); $pdf->SetFillColor($tableRowFillColour, $tableRowFillColour, $tableRowFillColour); $pdf->SetFont("Arial", "", 15); for ($i=0; $iCell(36, 12, ("$" . number_format($dataRow[$i])), 1, 0, "C", $fill); } $row++; $fill = !$fill; $pdf->Ln(12); }

Создаем график

Последним элементом в нашем отчете является столбиковый график, отображающий сводную информацию по четырем продуктам за весь год.

Вычисление масштаба и ширины столбика

Сначала надо вычислить масштаб для осей X и Y. Для масштаба по оси X вычисления заключаются в простом делении количества продуктов на желаемую ширину графика (нужно учесть небольшие отступы слева и справа для лучшего вида):

/*** Создаем график ***/ // Вычисляем масштаб по оси X $xScale = count($rowLabels) / ($chartWidth - 40);

Для вычисления масштаба по оси Y нужно найти общее значение по каждому продукту и затем определить среди них максимальное значение. Затем максимум можно будет разделить на желаемую высоту графика для получения значения масштаба по оси Y:

// Вычисляем масштаб по оси Y $maxTotal = 0; foreach ($data as $dataRow) { $totalSales = 0; foreach ($dataRow as $dataCell) $totalSales += $dataCell; $maxTotal = ($totalSales > $maxTotal) ? $totalSales: $maxTotal; } $yScale = $maxTotal / $chartHeight;

Теперь, зная масштаб по оси X, можно вычислить ширину (в мм) каждого столбца графика. Это инверсированное значение масштаба по оси X, уменьшенное в полтора раза для организации расстояния между столбцами:

// Вычисляем ширину столбцов $barWidth = (1 / $xScale) / 1.5;

Добавляем линии осей и метки на них

Теперь можно добавить линии осей X и Y, метки данных и метки осей. Используем шрифт Arial с размером 10 для меток данных.

Для вывода линии в FDPF используется метод Line() , которые принимает четыре аргумента: координаты X и Y начала линии, и координаты X и Y конца линии.

Для оси X выводим горизонтальную линию вдоль низа графика, оставляя 30 мм для меток по оси Y слева. Затем выводим каждое имя продукта в массиве $rowLabels как текстовую ячейку в соответствующую точку:

// Добавляем оси: $pdf->SetFont("Arial", "", 10); // Ось X $pdf->Line($chartXPos + 30, $chartYPos, $chartXPos + $chartWidth, $chartYPos); for ($i=0; $i < count($rowLabels); $i++) { $pdf->SetXY($chartXPos + 40 + $i / $xScale, $chartYPos); $pdf->Cell($barWidth, 10, $rowLabels[$i], 0, 0, "C"); }

Метод SetXY() позволяет устанавливать текущую позицию в нужное место на странице.

Для оси Y выводим вертикальную линию слева от графика, оставляя 30 мм для меток данных по оси Y. Линию оси делаем на 8 мм больше желаемой высоты графике для того, чтобы было место для вывода метки оси. Затем организуем цикл от нуля до максимального значения данных $maxTotal , которое было определено ранее. Размер шага установлен в переменной $chartYStep (20,000). На каждом шаге выводим текущее значение выровненной вправо и короткую метку:

// Ось Y $pdf->Line($chartXPos + 30, $chartYPos, $chartXPos + 30, $chartYPos - $chartHeight - 8); for ($i=0; $i SetXY($chartXPos + 7, $chartYPos - 5 - $i / $yScale); $pdf->Cell(20, 10, "$" . number_format($i), 0, 0, "R"); $pdf->Line($chartXPos + 28, $chartYPos - $i / $yScale, $chartXPos + 30, $chartYPos - $i / $yScale); }

Теперь можно добавить метки осей. Используем шрифт Arial полужирный с размером 12. Размещаем метку оси X ниже меток данных, а метку оси Y - наверху оси Y:

// Добавляем метки осей $pdf->SetFont("Arial", "B", 12); $pdf->SetXY($chartWidth / 2 + 20, $chartYPos + 8); $pdf->Cell(30, 10, $chartXLabel, 0, 0, "C"); $pdf->SetXY($chartXPos + 7, $chartYPos - $chartHeight - 12); $pdf->Cell(20, 10, $chartYLabel, 0, 0, "R");

Выводим столбцы графика

Завершающей стадией является создание самого графика. Для вывода столбцов используется метод FPDF Rect() , который выводит прямоугольник. Метод использует следующие аргументы:

  • Координаты X и Y верхнего левого угла прямоугольника.
  • Ширина и высота прямоугольника.
  • Стиль прямоугольника. Может иметь значения "D" или "" (выводим обводку), "F" (заполняем текущим цветом фона), или "DF" / "FD" (обводка и заполнение).

Теперь выводим столбцы. Установим переменную $xPos , которая служит для отслеживания текущей позиции по X. Зададим ей значение 40 мм с учетом расстояния для меток по оси Y и отступа для первого столбца. Теперь создадим переменную $bar , которая будет содержать номер текущего столбца. Она будет использоваться для установки цвета для столбца:

// Создаем столбецы $xPos = $chartXPos + 40; $bar = 0;

Теперь проходим циклом по массиву $data , вычисляем суммарное значение для каждой строки и выводим столбец от оси X до этого значения, масштабированного с помощью $yScale . Цвет для каждого столбца изменяется с помощью счетчика $bar , который является индексом в массиве $chartColours . После вывода текущего столбца перемещаем позицию X к началу следующего, увеличиваем счетчик $bar и продолжаем цикл:

Foreach ($data as $dataRow) { // Вычисляем суммарное значение по строке данных для продукта $totalSales = 0; foreach ($dataRow as $dataCell) $totalSales += $dataCell; // Создаем столбец $colourIndex = $bar % count($chartColours); $pdf->SetFillColor($chartColours[$colourIndex], $chartColours[$colourIndex], $chartColours[$colourIndex]); $pdf->Rect($xPos, $chartYPos - ($totalSales / $yScale), $barWidth, $totalSales / $yScale, "DF"); $xPos += (1 / $xScale); $bar++; }

В коде используется оператор PHP деление по модулю (%) для повтора цвета столбца, если количество столбцов превышает количество элементов в массиве $chartColours .

Отправляем документ PDF браузеру

Документ PDF готов! Осталось только отправить его браузеру, чтобы пользователь мог просмотреть его или загрузить.

Для этого используется метод FPDF Output() . Он принимает два аргумента: предполагаемое имя для PDF файла и флаг назначения. Данный флаг может принимать следующие значения:

    I: Выводить PDF на экран, если такая функция поддерживается браузером, иначе загружать.

    D: Загружать PDF.

    F: Сохранять файл в папке на сервере.

    S: Возвращать данные PDF как строку.

Для нашего примера используется опция I для вывода PDF на экран, если возможно:

/*** Выводим PDF ***/ $pdf->Output("report.pdf", "I"); ?>

Output() автоматически посылает заголовок HTTP "Content-type: application/pdf" , который сигнализирует браузеру о том, что следует ожидать документ PDF.

Теперь вы готовы протестировать скрипт. Открывайте браузер и переходите на URL, где расположен скрипт, например, www.example.com/report.php . Вы должны увидеть PDF в окне браузера. Или будет выведено диалоговое окно, в котором вам будет предложено сохранить документ PDF на вашем жестком диске. Вы можете потом открыть PDF файл в программе для просмотра PDF, например, в Acrobat Reader или Preview.

Для создания PDF документа нужен только PHP и FPDF.

Заключение

В данном уроке вы узнали как использовать PHP с библиотекой FPDF для генерации отчета в формате PDF. Были продемонстрированы методы библиотеки FPDF для создания текста, таблиц и графиков.

Однако библиотека FPDF может много чего еще, например, создавать верхний и нижний колонтитулы для страниц, использовать автоматический переход на новую страницу и так далее. Просмотрите документацию по библиотеке на сайте FPDF .

Для того, чтобы генерировать PDF файл из HTML, мы будем использовать библиотеку DomPDF для PHP. И вместе с ней мы сможем получить качественно сгенерированные PDF файлы с русскими символами.

Итак, приступим. Для начала необходимо скачать саму библиотеку по адресу:

Или установить её через composer:

Composer require dompdf/dompdf

Однако, стоит отметить, что стандартная сборка НЕ поддерживает русскоязычные символы. Поэтому, приходится долго копать интернет и пробовать, пробовать, пробовать. Чтобы сократить Ваше время, мы уже собрали все. Ниже, Вы сможете скачать библиотеку с поддержкой русскоязычных символов.

Если Вы хотите использовать стандартную сборку, то просто замените файлы из данного архива (916 KB) .

Вам необходимо будет заменить файлы в папке:

../dompdf/lib/fonts

С данным скриптом Вы сможете формировать сложные PDF файлы с таблицами, изображениями, которые из HTML встроятся в PDF файл.

Мы используем эту библиотеку для генерации PDF при ajax запросе. В скачанном архиве Вы найдете файл index.php, который обрабатывает приходящие данные, подключает шаблон, в который уже встроены изображения. Мы выгрузили для Вас полностью рабочий и используемый нами вариант (5 MB) .

Скачать пример сгенерированного PDF файла (580 KB)

Если Вы скачали библиотеку, то подключите к Вашему PHP файлу её с помощью подключения автозагрузчика:

Require_once "dompdf/autoload.inc.php";

Или используйте GIT:

Git clone https://github.com/dompdf/dompdf.git
cd dompdf
git clone https://github.com/PhenX/php-font-lib.git lib/php-font-lib
cd lib/php-font-lib
git checkout 0.5.1
cd ..
git clone https://github.com/PhenX/php-svg-lib.git php-svg-lib
cd php-svg-lib
git checkout v0.3

Сам обработчик выглядит так:

//подключаем автозагрузчик include_once "autoload.inc.php"; //функция очистки кода от вредоносных данных function challsrt($data){ $array1=array("\"","*","%","0x","&","\0","\n","\r","\s","\t","\\","`","^","$","{","}","[","]","(",")","wss","blob","localhost","–","