С помощью расширения 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.
Класс с установленным кириллическим шрифтом Arial – dompdf.zip
Для примера сделаем счет на оплату:
Для удобства сформируем массив товаров по которому скрипт выведет таблицу и посчитает итоговую сумму и НДС.
$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="">
должны быть указаны относительно сервера. - У таблиц не получится задать ширину колонок тегом
<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 td {
padding: 5px;
}
table th {
padding: 5px;
font-weight: bold;
}
.header {
margin: 0 0 0 0;
padding: 0 0 15px 0;
font-size: 12px;
line-height: 12px;
text-align: center;
}
/* Реквизиты банка */
.details td {
padding: 3px 2px;
border: 1px solid #000000;
font-size: 12px;
line-height: 12px;
vertical-align: top;
}
h1 {
margin: 0 0 10px 0;
padding: 10px 0 10px 0;
border-bottom: 2px solid #000;
font-weight: bold;
font-size: 20px;
}
/* Поставщик/Покупатель */
.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="' . __DIR__ . '/demo/sign-1.png">
<img class="sign-2" src="' . __DIR__ . '/demo/sign-2.png">
<img class="printing" src="' . __DIR__ . '/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.
use Dompdf\Dompdf;
include_once __DIR__ . '/dompdf/autoload.inc.php';
$dompdf = new Dompdf();
$dompdf->loadHtml($html, 'UTF-8');
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();
// Вывод файла в браузер:
$dompdf->stream('schet-10');
// Или сохранение на сервере:
$pdf = $dompdf->output();
file_put_contents(__DIR__ . '/schet-10.pdf', $pdf);
В результате получится pdf файл.