С помощью расширения dompdf можно легко сформировать PDF файл. По сути, dompdf – это конвертер HTML в PDF который поддерживает CSS, атрибуты style и другие.
- Поддерживает большинство свойств CSS 2.1.
- Поддерживает сложные таблицы, включая индивидуальный стили ячеек.
- Поддержка изображений gif, png с прозрачностью, bmp и jpeg.
- PHP => 5.3 с установленными расширениями DOM, GD, MBString, php-font-lib, php-svg-lib.
Проект на GitHub.
Для примера сделаем счет на оплату:
Для удобства сформируем массив товаров по которому скрипт выведет таблицу и посчитает итоговую сумму и НДС.
$prods = array(
array(
'name' => 'Плита CERAMAGUARD FINE FISSURED (100 RH) 600*600*15',
'count' => 25.3,
'unit' => 'м2',
'price' => 1210,
'nds' => 18,
),
array(
'name' => 'Европодвес (0.5м)',
'count' => 100,
'unit' => 'шт.',
'price' => 5.50,
'nds' => 0,
),
array(
'name' => 'Профиль 20*20',
'count' => 10,
'unit' => 'м',
'price' => 550,
'nds' => 10,
),
);
Также понадобятся функции для форматирования цен и вывода суммы прописью.
// Форматирование цен.
function format_price($value)
{
return number_format($value, 2, ',', ' ');
}
// Сумма прописью.
function str_price($value)
{
$value = explode('.', number_format($value, 2, '.', ''));
$f = new NumberFormatter('ru', NumberFormatter::SPELLOUT);
$str = $f->format($value[0]);
// Первую букву в верхний регистр.
$str = mb_strtoupper(mb_substr($str, 0, 1)) . mb_substr($str, 1, mb_strlen($str));
// Склонение слова "рубль".
$num = $value[0] % 100;
if ($num > 19) {
$num = $num % 10;
}
switch ($num) {
case 1: $rub = 'рубль'; break;
case 2:
case 3:
case 4: $rub = 'рубля'; break;
default: $rub = 'рублей';
}
return $str . ' ' . $rub . ' ' . $value[1] . ' копеек.';
}
Далее нужно сверстать счёт в обычном HTML с CSS.
Некоторые замечания:
- В адреса картинок в
<img src="">
лучше указывать полные URL. - У таблиц не получится задать ширину колонок тегом
<col>
.
$html = '
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<style type="text/css">
* {font-family: arial;font-size: 14px;line-height: 14px;}
table {margin: 0 0 15px 0;width: 100%;border-collapse: collapse;border-spacing: 0;}
table th {padding: 5px;font-weight: bold;}
table td {padding: 5px;}
.header {margin: 0 0 0 0;padding: 0 0 15px 0;font-size: 12px;line-height: 12px;text-align: center;}
h1 {margin: 0 0 10px 0;padding: 10px 0;border-bottom: 2px solid #000;font-weight: bold;font-size: 20px;}
/* Реквизиты банка */
.details td {padding: 3px 2px;border: 1px solid #000000;font-size: 12px;line-height: 12px;vertical-align: top;}
/* Поставщик/Покупатель */
.contract th {padding: 3px 0;vertical-align: top;text-align: left;font-size: 13px;line-height: 15px;}
.contract td {padding: 3px 0;}
/* Наименование товара, работ, услуг */
.list thead, .list tbody {border: 2px solid #000;}
.list thead th {padding: 4px 0;border: 1px solid #000;vertical-align: middle;text-align: center;}
.list tbody td {padding: 0 2px;border: 1px solid #000;vertical-align: middle;font-size: 11px;line-height: 13px;}
.list tfoot th {padding: 3px 2px;border: none;text-align: right;}
/* Сумма */
.total {margin: 0 0 20px 0;padding: 0 0 10px 0;border-bottom: 2px solid #000;}
.total p {margin: 0;padding: 0;}
/* Руководитель, бухгалтер */
.sign {position: relative;}
.sign table {width: 60%;}
.sign th {padding: 40px 0 0 0;text-align: left;}
.sign td {padding: 40px 0 0 0;border-bottom: 1px solid #000;text-align: right;font-size: 12px;}
.sign-1 {position: absolute;left: 149px;top: -44px;}
.sign-2 {position: absolute;left: 149px;top: 0;}
.printing {position: absolute;left: 271px;top: -15px;}
</style>
</head>
<body>
<p class="header">
Внимание! Оплата данного счета означает согласие с условиями поставки товара.
Уведомление об оплате обязательно, в противном случае не гарантируется наличие
товара на складе. Товар отпускается по факту прихода денег на р/с Поставщика,
самовывозом, при наличии доверенности и паспорта.
</p>
<table class="details">
<tbody>
<tr>
<td colspan="2" style="border-bottom: none;">ЗАО "БАНК", г.Москва</td>
<td>БИК</td>
<td style="border-bottom: none;">000000000</td>
</tr>
<tr>
<td colspan="2" style="border-top: none; font-size: 10px;">Банк получателя</td>
<td>Сч. №</td>
<td style="border-top: none;">00000000000000000000</td>
</tr>
<tr>
<td width="25%">ИНН 0000000000</td>
<td width="30%">КПП 000000000</td>
<td width="10%" rowspan="3">Сч. №</td>
<td width="35%" rowspan="3">00000000000000000000</td>
</tr>
<tr>
<td colspan="2" style="border-bottom: none;">ООО "Компания"</td>
</tr>
<tr>
<td colspan="2" style="border-top: none; font-size: 10px;">Получатель</td>
</tr>
</tbody>
</table>
<h1>Счет на оплату № 10 от 01 февраля 2018 г.</h1>
<table class="contract">
<tbody>
<tr>
<td width="15%">Поставщик:</td>
<th width="85%">ООО "Компания", ИНН 0000000000, КПП 000000000, 125009, Москва г, Тверская, дом № 9</th>
</tr>
<tr>
<td>Покупатель:</td>
<th>ООО "Покупатель", ИНН 0000000000, КПП 000000000, 119019, Москва г, Новый Арбат, дом № 10
</th>
</tr>
</tbody>
</table>
<table class="list">
<thead>
<tr>
<th width="5%">№</th>
<th width="54%">Наименование товара, работ, услуг</th>
<th width="8%">Коли-<br>чество</th>
<th width="5%">Ед.<br>изм.</th>
<th width="14%">Цена</th>
<th width="14%">Сумма</th>
</tr>
</thead>
<tbody>';
$total = $nds = 0;
foreach ($prods as $i => $row) {
$total += $row['price'] * $row['count'];
$nds += ($row['price'] * $row['nds'] / 100) * $row['count'];
$html .= '
<tr>
<td align="center">' . (++$i) . '</td>
<td align="left">' . $row['name'] . '</td>
<td align="right">' . $row['count'] . '</td>
<td align="left">' . $row['unit'] . '</td>
<td align="right">' . format_price($row['price']) . '</td>
<td align="right">' . format_price($row['price'] * $row['count']) . '</td>
</tr>';
}
$html .= '
</tbody>
<tfoot>
<tr>
<th colspan="5">Итого:</th>
<th>' . format_price($total) . '</th>
</tr>
<tr>
<th colspan="5">В том числе НДС:</th>
<th>' . ((empty($nds)) ? '-' : format_price($nds)) . '</th>
</tr>
<tr>
<th colspan="5">Всего к оплате:</th>
<th>' . format_price($total) . '</th>
</tr>
</tfoot>
</table>
<div class="total">
<p>Всего наименований ' . count($prods) . ', на сумму ' . format_price($total) . ' руб.</p>
<p><strong>' . str_price($total) . '</strong></p>
</div>
<div class="sign">
<img class="sign-1" src="https://example.com/demo/sign-1.png">
<img class="sign-2" src="https://example.com/demo/sign-2.png">
<img class="printing" src="https://example.com/demo/printing.png">
<table>
<tbody>
<tr>
<th width="30%">Руководитель</th>
<td width="70%">Иванов А.А.</td>
</tr>
<tr>
<th>Бухгалтер</th>
<td>Сидоров Б.Б.</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>';
Передаём переменную $html
в dompdf. Библиотеку можно скачать по ссылке https://github.com/dompdf/dompdf/releases.
// Если на сайте используется автозагрузка классов
//spl_autoload_unregister('autoload');
include_once __DIR__ . '/dompdf/autoload.inc.php';
$dompdf = new Dompdf\Dompdf();
$dompdf->set_option('isRemoteEnabled', TRUE);
$dompdf->setPaper('A4', 'portrait');
$dompdf->loadHtml($html, 'UTF-8');
$dompdf->render();
// Вывод файла в браузер:
$dompdf->stream('schet');
// Или сохранение на сервере:
$pdf = $dompdf->output();
file_put_contents(__DIR__ . '/schet.pdf', $pdf);
В результате получится pdf файл.
Если используется не стандартный шрифт то нужно его установить по следующиму алгоритму:
1. Скачать шрифты в формате ttf для обычного и жирного начертания (например open-sans.ttf и open-sans-bold.ttf).
2. Скачать программу ttf2ufm (ttf2ufm.zip).
3. Запустить консоль (cmd), лучше от имени администратора.
4. Выполнить команды для всех файлов шрифтов по отдельности, подставив полные пути до файлов.
C:\ttf2ufm.exe -A -F -l russian C:\open-sans.ttf
C:\ttf2ufm.exe -A -F -l russian C:\open-sans-bold.ttf
5. На выходе получатся файлы:
open-sans.ttf
open-sans.ufm
open-sans.afm
open-sans-bold.ttf
open-sans-bold.ufm
open-sans-bold.afm
6. Копируем их на сайт, в директорию библиотеки /dompdf/lib/fonts
7. В файле dompdf_font_family_cache.dist.php
нужно прописать новый шрифт, добавив элемент в массив:
При использовании стандарных шрифтов (times-roman, helvetica и т.д.) если вместо кирилицы выводятся знаки вороса (???
), то нужно сделать те же действия как описаны ваше, заменив только файлы (.ufm и .afm) в /dompdf/lib/fonts
.
В файле dompdf_font_family_cache.dist.php
они уже прописаны.
У меня не получилось использовать Arial. Файлы сгенерил, положил в папку, но всё равно были ??? вместо кириллицы. В итоге использую font-family: dejavu serif
Внимание, НЮАНС (сам долго провозился, разбираясь в чём проблема): строка таблицы не должна быть больше высоты страницы pdf, иначе в пдф эта строка начинается с новой страницы и больше чем высота страницы содержимое этой строки не показывается.
PS:
задонатил 100 руб.
В моем dompdf нет такого файла вообще