heron
heron

Reputation: 3661

Working with PDF in PHP

Short

What I want to do is, to prepare PHP generated result for print with strong rules.

Tried all possible ways with css+html: set dimensions in px, mm, cm. Nothing helped. Each browser, even each printer printed absolutely different paper results (tried both with & w/o border print. also didn't get result). After long research, found that CSS is not best way for this purpose and better way - to use pdf creation functionality with PHP. So, installed TCPDF. But can't get it work with logical part that I created for HTML output.

What I want to get

Here is more detailed explanation on image:

enter image description here

What I'm getting

After form submission, processing in php side takes too long - about minute and opens blank page instead of PDF result.

Code:

(Code is not so huge, comments are making it look like so:)

<?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');
?>

Script works like that:

  1. User selects items' checkboxes
  2. After form submission, PHP gets values of checked checkboxes via Ajax
  3. In foreach loop, PHP gets quantities of each item from database.
  4. Generated table

Upvotes: 8

Views: 18053

Answers (3)

Jared Farrish
Jared Farrish

Reputation: 49188

I think that if you're not getting a result at all, you likely are suppressing errors in a way you can't you're getting them with your script. Also, your approach with HTML is just not how it works; you can't interleave the TCPDF native cell calls with HTML; they're not "outputting" markup. So you're mixing two different, incompatible formats, that are going to two different buffers.

However, you code should still generate a PDF.

Note the last page, with your markup-generated content.

The only changes I made was to make it where I could run it without access to your data:

$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++;
    }
}

I get a PDF. It looks nothing like what you have in the image, but it does produce a PDF. I see that your code is about 90% similar to this example on the TDPDF site:

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

When I went in and made my own example, I was able to get a PDF that generally mimicked what you show in the photo. As you'll see in the code I have below, you have to work with the native TCPDF cell methods to get the barcode generation to work. It's not that hard; took me about 30 minutes to figure out how to produce a pdf.

The only thing I couldn't figure out was where the black line on the top comes from; it's somehow associated with the header, but I couldn't find where to turn it off. The code that's behind the second 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');

?>

Upvotes: 2

Iannazzi
Iannazzi

Reputation: 1388

Here is a link to a pdf that looks exactly like your image:

Link to embrasse-moi.com barcode label file

AND here is the function that created it. I use tcpdf. I create 3 lines of text, the id, the description, the price, which I lookup from my sub-id, so that code you will have to replace. I also pass in the row/column offset for use with avery5167 so we can use all the stickers.

    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
    //============================================================+
    }

Upvotes: 0

redmoon7777
redmoon7777

Reputation: 4526

here is an html/css to pdf converter library http://www.mpdf1.com/mpdf/

This has it's own html/css parser and thus will yield the same result in all browser.

<?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;

?>

Upvotes: 4

Related Questions