Постановка задачи
Был у меня однажды интересный заказ. Владелец одной крупной украинской компании «Укрзолото» захотел сэкономить на дизайнерах и автоматически генерировать PDF-файлы уже готовые к печати, в которых компактно и красиво были бы расположены изображения (разрешением 300 dpi специально для печати) ювелирных изделий. Все изображения изделий (кстати, размеры разные) предварительно через админ-web-интерфейс загружались на сервер и после через форму выбора формировался массив идентификаторов данных из базы, плюс настройки самого PDF. Для генерации PDF была выбрана библиотека
FPDF.
Необходимо выбрать категорию ювелирных изделий:
Для наглядности показать изображения, выбрать формат будущего документа (А4, А5), язык (русский, украинский, английский) и, само-собой, отметить чекбоксами те изображения, которые должны попасть в PDF:
После нажатия на кнопку «Печатная версия (PDF)» появляется запрос скачать и сохранить уже сгенерированный файл:
В имени файла присутствует номер категории. В данном случае при выборе серёжек категория равна 10.
Для наглядности выбрал «Серьги» и «Броши».
Результат можно скачать и посмотреть:
Серьги 10-ukrzoloto.pdf
Броши 27-ukrzoloto.pdf
Реализация
Но нас интересует самое главное — скрипт с алгоритмом генерации! Итак, сначала настройки.
// подключаем всё, что можно подключить
define("FPDF_FONTPATH","путь к папке /font/");
require("путь к классу fpdf.class.php");
include_once "путь к файлу подключения к базе данных";
Тепперь небольшой нюанс. Дело в том, что требования к печати диктуют 300 точек на дюйм, а значит нам необходим коэффициент перерасчёта.
// A4 portrait - 210x297 mm = 2480x3508 px (300dpi)
// A5 landscape - 210x148.5 mm = 2480x1754 px (300dpi)
// коэффициент перехода при 300dpi
$k=11.8;
Определяем формат будущего файла исходя из данных формы:
// если формат А5, то альбомное расположение
// если формат А4, то книжное расположение
if($_POST['format45']=="A5") $_POST['formatPL']="L";
if($_POST['format45']=="A4") $_POST['formatPL']="P";
Создаём экземпляр класса с тонкими настройками (расположение, миллиметры, формат):
$pdf = new FPDF($_POST['formatPL'],'mm',$_POST['format45']);
Далее:
$pdf->SetAuthor("ukrzoloto"); // автор документа
$pdf->SetCreator("programilla.com"); // создатель документа
$pdf->SetTitle("ukrzoloto"); // заголовок документа
$pdf->SetMargins(10,10,10,10); // отступы по краям страниц в миллиметрах
$pdf->AddFont("BalticaC","","Baltica.php"); // Подключаем кириллический шрифт
$pdf-> SetFont("BalticaC","",9); // устанавливаем шрифт
$pdf->SetDrawColor(181,161,153); // устанавливаем цвет рамки изображения
Далее надо напомнить, что у нас есть массив индентификаторов товаров
// массив идентификаторов товаров
$arrId = какие-то преобразования с массивом($_POST['arrId']);
Создаём все необходимые массивы: для ширины и высоты изображений, для артикула и имён файлов, для веса.
for($i=0; $i<count($arrId); $i++){
...
$arrJpg[$i] // массив названий файлов
$arrArt[$i] // массив артикулов
$arrW[$i] // массив ширин файлов в пикселях
$arrH[$i] // массив высот файлов в пикселях
$arrM[$i] // массив масс товаров в граммах
...
};
Находим максимальные значения ширины и высоты изображений в mm
$maxW=max($arrW)/$k;
$maxH=max($arrH)/$k;
Определяем расстояния (отступы) между колонками и строками изображений. Эти параметры выставляются вручную из соображения визуальной эстетики )))
$tabX=4; // расстояние по оси X (по ширине)
$tabY=15; // расстояние по оси Y (по высоте)
Расчитываем количество колонок (20 берётся из отступов 10+10 по краям документа, см. выше)
$numTD=floor((210-20+$tabX)/($maxW+$tabX));
Расчитываем количесво строк на странице
if($_POST['format45']=="A4"){ $numTR=floor((297-20)/($maxH+$tabY)); };
if($_POST['format45']=="A5"){ $numTR=floor((148.5-20)/($maxH+$tabY)); };
Расчитываем количество товаров на одной странице
$numIdPerPage=$numTD*$numTR;
Расчитываем количество страниц
$numP=ceil(count($arrId)/$numIdPerPage);
Установку языка можно опустить по причинам несущественности в рамках задачи.
Алгоритм
for($page=0; $page<$numP; $page++){
$pdf->AddPage(); // создаём страницу PDF
for($tr=0; $tr<$numTR; $tr++){
for($td=0; $td<$numTD; $td++){
// вводим индентификатор товара-файла
$i=$td+$tr*$numTD+$page*$numIdPerPage;
// если файл-изображение найден и существует, то прорисовывать вывод всех данных
if(file_exists("../img/data/".$arrJpg[$i].".jpg")){
// вводим индикатор перехода на новую строку
if($td==$numTD-1){ $ind=1; }else{ $ind=0; };
// определяем отступы для центрирования изображения в рамке
$tabW=($maxW-$arrW[$i]/$k)/2; // отступ по оси X (по ширине)
$tabH=($maxH-$arrH[$i]/$k)/2; // отступ по оси Y (по высоте)
// показываем изображения
$pdf->Image("../img/data/".$arrJpg[$i].".jpg",(10+$td*($maxW+$tabX)+$tabW),(10+$tr*($maxH+$tabY)+$tabH),$arrW[$i]/$k);
// показываем рамки для картинок
$pdf->SetXY((10+$td*($maxW+$tabX)),(10+$tr*($maxH+$tabY))); // устанавливаем координаты
$pdf->Cell($maxW,$maxH,'',1,$ind,'C'); // рисуем рамку
$pdf->Cell($tabX,0,'',0,$ind); // делаем отступ вправо для следующей рамки
// показываем вес
$pdf->SetXY((10+$td*($maxW+$tabX)),(10+$maxH+1+$tr*($maxH+$tabY))); // устанавливаем координаты
$pdf->Cell($maxW,5,$lng_mass.$arrM[$i],0,$ind,'C'); // пишем массу
$pdf->Cell($tabX,0,'',0,$ind); // делаем отступ вправо для следующей записи
// показываем артикул
$pdf->SetXY((10+$td*($maxW+$tabX)),(10+$maxH+5+$tr*($maxH+$tabY))); // устанавливаем координаты
$pdf->Cell($maxW,5,$lng_art.$arrArt[$i],0,$ind,'C'); // пишем артикул
$pdf->Cell($tabX,0,'',0,$ind); // делаем отступ вправо для следующей записи
};
};
};
};
Рисуем PDF с таким-то именем, параметр D — отправить в браузер и предложить скачать
$pdf->Output($art_cat_title."-ukrzoloto.pdf", "D");
Собственно говоря и всё. Если Вы скачаете небольшие два сгенерированных документа, то в них всё будет наглядно показано, как с помощью PHP и библиотеки FPDF можно действительно делать такую красоту. Для тех, кто хочет развить тему могу посоветовать сделать оригинальную красивую подложку для документа и буклет полностью готов!
Комментарии (1)
RSS свернуть / развернутьhalkin
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.