Работа с PDF в PHP - PullRequest
       11

Работа с PDF в PHP

8 голосов
/ 12 февраля 2012

Short

Я хочу подготовить сгенерированный PHP результат для печати по строгим правилам.

Перепробовал все возможные способы с помощью css + html: задайте размеры в пикселях, мм, см. Ничего не помогло Каждый браузер, даже каждый принтер печатал абсолютно разные результаты на бумаге (пробовал как с & без печати границы. Также не получил результат). После долгих исследований выяснилось, что CSS не лучший способ для этой цели и лучший способ - использовать функциональность создания PDF с PHP. Итак, установлен TCPDF. Но не могу заставить его работать с логической частью, которую я создал для вывода HTML.

Что я хочу получить

  • Поля в первой и последней строках таблицы от сверху и снизу стороны листа должны быть 11 мм
  • Поля между рядами 0 мм
  • Строки таблицы должны быть на 4 мм с с левой и правой сторон бумаги
  • 2 мм между столбцами
  • 38 мм ширина x 21,2 мм высота каждая ячейка
  • 13 x строк, 5 x столбцов, 13x5 = 65 ячеек
  • Каждая таблица на новой странице. Другими словами - после каждой таблицы разрыв страницы
  • В каждой ячейке штрих-код Code 39 (значение должно быть $id)
  • Только таблицы в формате PDF - без заголовка, без нижнего колонтитула, без заголовка ... и т.д.

Вот более подробное объяснение на картинке:

enter image description here

Что я получаю

После отправки формы обработка на стороне php занимает слишком много времени - около минуты и открывает пустую страницу вместо результата PDF.

Код:

(Код не такой большой, комментарии заставляют его выглядеть так:)

<?php
require_once('tcpdf/config/lang/eng.php');
require_once('tcpdf/tcpdf.php');

// create new PDF document
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);

$pdf->SetPrintHeader(false);
$pdf->SetPrintFooter(false);
// set document information
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetAuthor('John Smith');
$pdf->SetTitle(false);
$pdf->SetSubject(false);
$pdf->SetKeywords(false);

// set default header data.set all false because don't want to output header footer
$pdf->SetHeaderData(false, false, false, false);

// set header and footer fonts
$pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
$pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));

// set default monospaced font
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);

//set margins
$pdf->SetMargins(4, 11, 4);
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER);

//set auto page breaks
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);

//set image scale factor
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);

//set some language-dependent strings
$pdf->setLanguageArray($l);

// ---------------------------------------------------------
// set font
$pdf->SetFont('helvetica', '', 10);

// add a page
$pdf->AddPage();

// define barcode style
$style = array(
    'position' => '',
    'align' => 'C',
    'stretch' => false,
    'fitwidth' => true,
    'cellfitalign' => '',
    'border' => true,
    'hpadding' => 'auto',
    'vpadding' => 'auto',
    'fgcolor' => array(0, 0, 0),
    'bgcolor' => false, //array(255,255,255),
    'text' => true,
    'font' => 'helvetica',
    'fontsize' => 8,
    'stretchtext' => 4
);

ob_start();
?>



<style type="text/css">

    table { 

        width: 100%;          

        border-collapse: collapse;

    }

    td img {
        height:10mm;
    }

    td {
        padding: 0 1mm 0 1mm;
        vertical-align:middle;              
    }

    .cell {
        width: 38mm;
        height:21mm;
        font-style: bold;
        text-align: center; 
    }

    tr    { 
        height:21mm;
        margin:0;
        padding:0;            
    }


</style>

<?php

$i = 0;
$item = new item($db);
foreach ($_POST['checkbox'] as $id) {
    $details = $item->getDetails($id);
    $qt = (isset($_POST['qt'])) ? $_POST['qt'] : $details['qt'];
    for ($cnt = 1; $cnt <= $qt; $cnt++) {
        // check if it's the beginning of a new table
        if ($i % 65 == 0)
            echo '<table>';

        // check if it's the beginning of a new row
        if ($i % 5 == 0)
            echo '<tr>';

        echo '<td><div class="cell">www.fety.fr<br/>';
        $pdf->Cell(0, 0, 'CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9', 0, 1);
        $pdf->write1DBarcode($id, 'C39', '', '', '', 18, 0.4, $style, 'N');
        $pdf->Ln();
        echo '<br/>' . $details['hcode'] . '</div></td>';

        // check if it's the end of a row
        if (($i + 1) % 5 == 0)
            echo '</tr>';

        // check if it's the end of a table
        if (($i + 1) % 65 == 0)
            echo '</tr></table>';

        $i++;
    }
}

// if the last table isn't full, print the remaining cells
if ($i % 65 != 0) {
    for ($j = $i % 65; $j < 65; $j++) {
        if ($j % 65 == 0)
            echo '<table>';
        if ($j % 5 == 0)
            echo '<tr>';
        echo '<td></td>';
        if (($j + 1) % 5 == 0)
            echo '</tr>';
        if (($j + 1) % 65 == 0)
            echo '</table>';
    }
}

$markup = ob_get_clean();

// output the HTML content
$pdf->writeHTML($markup, true, false, true, false, '');



// reset pointer to the last page
$pdf->lastPage();

// ---------------------------------------------------------
//Close and output PDF document
$pdf->Output('bcsheet.pdf', 'I');
?>

Сценарий работает так:

  1. Пользователь выбирает чекбоксы элементов
  2. После отправки формы PHP получает значения отмеченных флажков через Ajax
  3. В цикле foreach PHP получает количество каждого элемента из базы данных.
  4. Генерируемая таблица

Ответы [ 3 ]

4 голосов
/ 12 февраля 2012

вот библиотека конвертеров html / css в pdf http://www.mpdf1.com/mpdf/

У него есть собственный html / css-анализатор, и, следовательно, он даст одинаковый результат во всех браузерах.

<?php

$html = '
    <html>
    <head>
    <style>
        table {
        width: 100%;
            border-collapse: collapse;
        }       
        tr {

        }
        td {
            width: 38mm;
            height: 21.2mm;
            margin: 0 1mm;
            text-align: center;
            vertical-align:middle; 
        }
    </style>
    </head>
    <body>
    <table>';

    for ($i = 0; $i < 13; $i++)
    {
        $html .= '<tr>';
        for($j = 0; $j < 5; $j++)
        {
            $html .= '<td><barcode code="TEC-IT" type="C39" class="barcode" /></td>';
        }
        $html .= '</tr>';
    }       

$html .= '</table>
    </body>
    </html>';

    include("MPDF53/mpdf.php");

    $mpdf = new mPDF('c', 'A4', '', '', 4, 4, 10.7, 10.7, 0, 0);

    $mpdf->SetDisplayMode('fullpage');

    $mpdf->list_indent_first_level = 0;

    $mpdf->WriteHTML($html,0);

    $mpdf->Output('test.pdf','I');
    exit;

?>
2 голосов
/ 12 февраля 2012

Я думаю, что если вы вообще не получаете результат, вы, скорее всего, подавляете ошибки так, как не можете получить их с помощью своего сценария.Кроме того, ваш подход к HTML не совсем так, как он работает;вы не можете чередовать вызовы собственных ячеек TCPDF с HTML;они не "выводят" разметку.Таким образом, вы смешиваете два разных несовместимых формата, которые собираются в два разных буфера.

Однако ваш код все равно должен генерировать PDF.

Обратите внимание на последнюю страницу с вашей разметкойсгенерированный контент.

Единственные изменения, которые я сделал, - сделать так, чтобы я мог запускать его без доступа к вашим данным:

$i = 0;
//$item = new item($db);
//foreach ($_POST['checkbox'] as $id) {
for ($id = 0; $id < 1; $id++) {
    //$details = $item->getDetails($id);
    //$qt = (isset($_POST['qt'])) ? $_POST['qt'] : $details['qt'];
    $details = array('These are details');
    $qt = 50;
    for ($cnt = 1; $cnt <= $qt; $cnt++) {
        // check if it's the beginning of a new table
        if ($i % 65 == 0)
            echo '<table>';

        // check if it's the beginning of a new row
        if ($i % 5 == 0)
            echo '<tr>';

        echo '<td><div class="cell">www.fety.fr<br/>';
        $pdf->Cell(0, 0, 'CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9', 0, 1);
        $pdf->write1DBarcode($id, 'C39', '', '', '', 18, 0.4, $style, 'N');
        $pdf->Ln();
        echo '<br/>' . $details['hcode'] . '</div></td>';

        // check if it's the end of a row
        if (($i + 1) % 5 == 0)
            echo '</tr>';

        // check if it's the end of a table
        if (($i + 1) % 65 == 0)
            echo '</tr></table>';

        $i++;
    }
}

Я получаю PDF.Это не похоже на то, что у вас есть на изображении, но оно создает PDF.Я вижу, что ваш код примерно на 90% похож на этот пример на сайте TDPDF:

http://www.tcpdf.org/examples/example_027.phps

Когда я вошел и создал свой собственный пример, я смог получить PDFчто в целом имитирует то, что вы показываете на фото.Как вы увидите из приведенного ниже кода, у вас есть для работы с нативными методами ячеек TCPDF, чтобы заставить генерацию штрих-кода работать.Это не так сложно;Мне понадобилось около 30 минут, чтобы понять, как создать PDF.

Единственное, что я не мог понять, это откуда взялась черная линия сверху;это как-то связано с заголовком, но я не смог найти где его отключить.Код, который стоит за вторым PDF:

<?php

require_once('tcpdf/config/lang/eng.php');
require_once('tcpdf/tcpdf.php');

// create new PDF document
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);

//set auto page breaks
$pdf->SetAutoPageBreak(TRUE);

//set image scale factor
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);

//set some language-dependent strings
$pdf->setLanguageArray($l);

$pdf->SetFont('helvetica', '', 10);

// define barcode style
$style = array(
    'position' => '',
    'align' => 'L',
    'stretch' => true,
    'fitwidth' => false,
    'cellfitalign' => '',
    'border' => true,
    'hpadding' => 'auto',
    'vpadding' => 'auto',
    'fgcolor' => array(0,0,0),
    'bgcolor' => false, //array(255,255,255),
    'text' => true,
    'font' => 'helvetica',
    'fontsize' => 8,
    'stretchtext' => 4
);

for ($o = 0; $o < 5; $o++) {
    $pdf->AddPage();

    $y = 10;

    for ($i = 0; $i < 13; $i++) {
        $x = 10;

        for ($p = 0; $p < 5; $p++) {
            // UPC-E
            $pdf->write1DBarcode('04210000526', 'UPCE', $x, $y, 37, 20, 0.4, $style);

            $x = $x + 38;
        }

        $y = $y + 21;

        $pdf->Ln();
    }
}

//Close and output PDF document
$pdf->Output('example_027.pdf', 'I');

?>
0 голосов
/ 19 февраля 2013

Вот ссылка на PDF, который выглядит точно так же, как ваше изображение:

Ссылка на файл этикетки штрих-кода embrasse-moi.com

И вот функция, которая его создала. Я использую tcpdf. Я создаю 3 строки текста, идентификатор, описание, цену, которую я ищу из моего подидида, так что этот код вам придется заменить. Я также передаю смещение строки / столбца для использования с avery5167, чтобы мы могли использовать все наклейки.

    function printProductLabelsAvery5167($product_sub_ids, $quantities, $row_offset, $column_offset, $filename)
{
    // Embrasse-moi.com
    require_once('../../../3rdParty/tcpdf/config/lang/eng.php');
    require_once('../../../3rdParty/tcpdf/tcpdf.php');

    $pdf_file_name = $filename;

    $subid = array();
    $poc_title = array();
    $color_price = array();

    for($i=0;$i<sizeof($product_sub_ids);$i++)
    {
        $pos_product_sub_id = $product_sub_ids[$i];
        $pos_product_id = getProductIdFromProductSubId($pos_product_sub_id);
        for($qty=0;$qty<$quantities[$i];$qty++)
        {
            $subid[] = getProductSubIDName($pos_product_sub_id);
            $poc_title[] = substr(getProductTitle($pos_product_id),0,48);
            $color_price[] = substr(getProductSubIdColorDescription($pos_product_sub_id),0,38) . '     $' . number_format(getProductRetail($pos_product_id),2);
        }
    }

    $margin_left = 0;
    $margin_right = 0;
    $margin_top = 0;
    $margin_bottom = 0;
    $cell_width = 1.75;
    $cell_height = 0.5;
    $cell_spacing = 0.3;
    $columns = 4;
    $rows = 20;
    $line_spacing_adjust = 0.015;
    $barcode_spacing_adjust = 0.1;
    $barcode_height_adjust = 0.05;

    $title = 'Avery 5167 template';
    $subject = 'PO # 123';
    $keywords = 'purchase order 123';
    $page_orientation = 'P';
    $page_format = 'LETTER';
    $unit = 'in';

    // create new PDF document
    $pdf = new TCPDF($page_orientation, $unit, $page_format, true, 'UTF-8', false);
    // set document information
    $pdf->SetCreator(COMPANY_NAME);
    $pdf->SetAuthor(getUserFullName($_SESSION['pos_user_id']));
    $pdf->SetTitle($title);
    $pdf->SetSubject($subject );
    $pdf->SetKeywords($keywords);
    $pdf->setPrintHeader(false);
    $pdf->setPrintFooter(false);
    $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
    $pdf->SetMargins($margin_left, $margin_top, $margin_right);
    $pdf->SetAutoPageBreak(TRUE, $margin_bottom);
    $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
    $pdf->setLanguageArray($l);
    $preferences = array('PrintScaling' => 'None');
    $pdf->setViewerPreferences($preferences);
    $pdf->SetFont('helvetica', 'R', 5);

    //barcode: 128a?
    // define barcode style
    $barcode_style = array(
    'position' => '',
    'align' => 'C',
    'stretch' => false,
    'fitwidth' => false,
    'cellfitalign' => '',
    'border' => false,
    'hpadding' => '0',
    'vpadding' => '0',
    'fgcolor' => array(0,0,0),
    'bgcolor' => false, //array(255,255,255),
    'text' => false,
    'font' => 'helvetica',
    'fontsize' => 4,
    'stretchtext' => 0
);


    // set border width
    $pdf->SetLineWidth(0.01);
    $pdf->SetDrawColor(0,0,0);
    //$pdf->setCellHeightRatio(3);
    $counter = 0;

    //calculating the pages.... how many labels are to be printed on the sheet...
    //how many labels are going on the first sheet?
    $first_page_number_of_spots = ($rows)*($columns-($column_offset-1)) -($row_offset-1);
    $number_of_labels = sizeof($subid);
    if($number_of_labels <= $first_page_number_of_spots)
    {
        $pages = 1;
    }
    else
    {
        $lables_on_first_page = $first_page_number_of_spots;
        $labels_remaining = $number_of_labels -$lables_on_first_page;
        $number_of_spots_per_page = $rows*$columns;
        $pages = ceil($labels_remaining/($number_of_spots_per_page)) + 1;
    }
    for($page=0;$page<$pages;$page++)
    {
        $pdf->AddPage();
        for($col=$column_offset-1;$col<$columns;$col++)
        {
            for($row=$row_offset-1;$row<$rows;$row++)
            {
                if($counter< sizeof($subid))
                {
                    //barcodes must be cap
                    $line1 = strtoupper($subid[$counter]);
                    $line2 = $poc_title[$counter];
                    $line3 = $color_price[$counter];
                }
                else
                {
                    $line1 = '';
                    $line2 = '';
                    $line3 = '';
                }
                $counter++;
                $x_spot = $cell_spacing + $col*$cell_width + $col*$cell_spacing;
                $y_spot = $cell_height + $row*$cell_height;
                $coords = 'X:'.$x_spot . ' Y:' .$y_spot;
                $border = 0;
                $border2 = 0;
                //this is the cell that will allow allignment to sticker checking
                $pdf->SetXY($x_spot, $y_spot);
                $pdf->Cell($cell_width, $cell_height,  '', $border, 0, 'C', 0, '', 0, false, 'T', 'M');

                // CODE 128 A
                $pdf->SetXY($x_spot+$barcode_spacing_adjust, $y_spot);
                //cell to check the barcode placement
                $pdf->Cell($cell_width-2*$barcode_spacing_adjust, $cell_height/2, '', $border, 0, 'C', 0, '', 0, false, 'T', 'M');
                $pdf->write1DBarcode($line1, 'C128A', $x_spot+$barcode_spacing_adjust, $y_spot+$barcode_height_adjust, $cell_width-2*$barcode_spacing_adjust, $cell_height/2 - $barcode_height_adjust, 0.4, $barcode_style, 'N');

                //the remaining 3 lines have to fit in 1/2 the sticker size
                //$y_offset = $cell_height/2;
                $pdf->SetXY($x_spot, $y_spot - 0*$line_spacing_adjust + 3/6*$cell_height);
                $pdf->Cell($cell_width, $cell_height/6,  $line1, $border2, 0, 'C', 0, '', 0, false, 'T', 'C');
                $pdf->SetXY($x_spot, $y_spot - 1*$line_spacing_adjust + 4/6*$cell_height);
                $pdf->Cell($cell_width, $cell_height/6,  $line2, $border2, 0, 'C', 0, '', 0, false, 'T', 'C');
                $pdf->SetXY($x_spot, $y_spot -2*$line_spacing_adjust + 5/6*$cell_height);
                $pdf->Cell($cell_width, $cell_height/6,  $line3, $border2, 0, 'C', 0, '', 0, false, 'T', 'C');


                //$pdf->writeHTMLCell($cell_width, $cell_height, $x_spot, $y_spot, $text_for_label, 1, 1, false, true, '', false);
                // no work $pdf->MultiCell($cell_width, $cell_height, $text_for_label, 1, 'J', false, '','',true, 0, false, true, $cell_height, 'T', false);
            }
            $row_offset = 1;
        }
        $column_offset = 1;
    }
    //Close and output PDF document
    $pdf->Output($pdf_file_name, 'D');

     //============================================================+
    // END OF FILE
    //============================================================+
    }
...