PDF Structure using tcpdf - php

I am creating PDF file with custom structure/layout using TCPDF library. Data is coming from server side and data is being displayed data in tabular form in PDF file.
PDF structure should be look like this
Required PDF structure
Based on my code. PDF structure/PDF structure based on my code
Actually, I this this layout in PDF file
Sheet Size : 210x297 mm (A4)
Format 6 (Row) x 3 (Col)
Label Size : 63.5 x 46.6
Margins : Left 7 mm, Right 8 mm, Gutter 2 mm
Top 10.4 mm Bottom 7 mm
I am using sheet size like this
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, array('210', '297'), true, 'UTF-8', false);
I am using Label (First column) size like this. I don't know it's correct or not but it looks like correct.
$subhtml .= '<td border="0" width="63.5mm" height="46.6mm style="float:left;text-align:left;">
I am using Margins (Left, Right,Top) like this and I don't know how to give gutter (space between two columns)
$pdf->SetMargins(7, 10.4, 8);
Bottom 7 MM like this
$pdf->SetFooterMargin(7);
PROBLEMS
Left side space is not same as in required PDF structure file.
How to give gutter/space between two columns.
All above code are correct or not?
Complete Code
$sql = "SELECT * FROM Members where MemberId in (select MemberId from Normalized_Category where Category IN (".addQuotes($categories)."))";
$result = mysqli_query($conn, $sql);
while($rows = mysqli_fetch_assoc($result)){
$members[] = $rows;
}
$subhtml ='';
$i = 1;
$j = 3;
$html ='';
foreach($members as $value){
$subhtml .= '<td border="0" width="63.5mm" height="46.6mm" style="float:left;text-align:left;">
<span>'.$value['MemberId'].'</span>
<span style="float:right; text-align:right;">'.$value['Expiry_Date'].'</span>
<br/><b>
<span>'.$value['Salute'].' '.$value['Name'].'</span>
</b><br/>
<span>'.$value['Address1'].','.$value['Address2'].','.$value['Address3'].' </span>
<br/><span>'.$value['City'].' '.$value['PinCode'].' - '.$value['State'].'</span><br/>
<span>'.$value['Contact'].'</span><br/></td>';
if ($i % $j == 0) {
$subhtml .= '</tr><tr>';
}
$i++;
}
$tbl = <<<EOD
<table border="0" cellpadding="2" align="justify">
<tr nobr="true">
<th colspan="3"></th>
</tr>
<tr nobr="true">
$subhtml
</tr>
</table>
EOD;
require('tcpdf/tcpdf.php');
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, array('210', '297'), true, 'UTF-8', false);
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->SetMargins(7, 10.4, 8); // left = 2.5 cm, top =
$pdf->SetFooterMargin(7);
if (#file_exists(dirname(__FILE__).'/lang/eng.php')) {
require_once(dirname(__FILE__).'/lang/eng.php');
$pdf->setLanguageArray($l);
}
$pdf->SetFont('helvetica', '', 9);
$pdf->AddPage();
$pdf->writeHTML($tbl, true, false, false, false, '');
$pdf->Output('Members.PDF', 'D');

Related

How to display images from mysql database without overlapping, FPDF?

I have a problem. I write codes of to display images from mysql database to FPDF but the images are displayed as overlapping (in same position)
<?php
include("connection.php");
$que1=mysql_query("select * from TableName);
ob_start();
require('fpdf/fpdf.php');
$pdf = new FPDF();
$pdf->AddPage();
while($rw=mysql_fetch_array($que1))
{
$profile=$rw['profile'];
$pdf->Image($profile,10,'',30);
}
$pdf->Output();
ob_end_flush();
?>
How can I display my images in vertical form?
Please anyone can help me.
The problem is with line
$pdf->Image($profile,10,'',30);
The first attribute is "file", Second is the axis X position, 3rd is axis Y, fourth is width.
Refference: Documentation
Please give different x,y values to prevent overlapping
From documentation I can see that Image method take [x, y] coordinates. So just for every image calculate new position:
$currentY = 0;
while ($rw = mysql_fetch_array()) {
$imageSize = $this->getSize($rw['profile']);
$pdf->Image($profile, 10, $currentY, 30);
$currentY += $imageSize['height'];
}
OR try setting y to null - Image($profile, 10, null, 30)

TCPDF SetAutoPageBreak() messes up scaling of my Footer()

I am using a custom Footer and have set its position with setY();. However, the content goes on behind my Footer, which means I needed to make my pagebreak higher. This resulted in messing up the size of my footer when I have more than one page.
My footer consists of tables with images inside. The thing that goes wrong, is that the images are getting weird sizes by some kind of scaling! The larger I make my setAutoPageBreak(), the more messed up my footer will become.
I've been at it for quite some hours. I hope someone can help me on this one.
My footer:
public function Footer() {
$footer = '<table>
<tr>
<td width="30" height="50"></td>
<td style="width: 570px; height: 55px;">
<img src="some_image" width="30" height="50" />
</td>
</tr>
</table>
';
$this->SetY(-60);
$this->writeHTML($footer, true, true, true, false, '');
}
TCPDF handling:
$pdf = new MyPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
set margins
$PDF_MARGIN_LEFT = 20;
$PDF_MARGIN_TOP = 40;
$PDF_MARGIN_RIGHT = 20;
$pdf->SetMargins($PDF_MARGIN_LEFT, $PDF_MARGIN_TOP, $PDF_MARGIN_RIGHT);
//LTRB
$PDF_MARGIN_HEADER = 5;
$PDF_MARGIN_FOOTER = 60;
$pdf->SetHeaderMargin($PDF_MARGIN_HEADER);
$pdf->SetFooterMargin($PDF_MARGIN_FOOTER);
// set auto page breaks, it also specifies margin-bottom. This scales the footer somehow...
$PDF_MARGIN_BOTTOM = 20;
$pdf->SetAutoPageBreak(true, $PDF_MARGIN_BOTTOM);
// set image scale factor
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
$pdf->AddPage();
// output the HTML content
$pdf->writeHTML($my_printed_html, true, false, true, false, '');
$pdf->Output('Test.pdf', 'I');
Editted:
I noticed the problem only occurs if my footer is below the pagebreak margin. If the footer is above it, the images are normal but the content passes the footer from behind.
Is there a way to bypass this?
The problem was solved quite easily, with a lot of regret of losing too much valuable time on this.
When you are using images in TCPDF, always match the size of the image with the desired size you want them to be in your pdf. The setImageScale() does not reach every image if it is outside the page range. That includes the footer, if its position is outside of the page margin_bottom.
I hope you guys won't hurt your heads too much about it and that this will save you all.

TCPDF execution timedout for larger table of SQL records

I am a beginner to php,I am using tcpdf class for generating PDF docs (contains html tables) for the SQL data.It converts the data as pdf for limited rows(200 rows but it takes 120sec ),but it can not able to do that for above 200 rows(shows maximum execution timed out).
I am using writehtml() function for writing html tables.
Is there any way to process larger records?
require_once('tcpdf/tcpdf.php');
$pdf = new TCPDF('P', PDF_UNIT,'A4', true, 'UTF-8', false);
$pdf->setFontSubsetting(false);
$pdf->SetHeaderData('logo.jpg',40,'companyhead',"addressline1,asdasd,\nxxxfgh-1234");
$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(PDF_MARGIN_LEFT, 30, PDF_MARGIN_RIGHT);
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
//selecting from the database and fetching each records
$query = "SELECT * FROM test3 WHERE month='$month[0]' AND year='$year[0]'";
$result = mysql_query($query);
while($rows = mysql_fetch_assoc($result))
{
//here goes some calculations with retrieved records
//add a page
$pdf->AddPage();
$pdf->SetFont('Times', 'B', 15);
$pdf->Write(0,'Pay slip for'.$month.','.$year.'', '', 0, 'C', true, 0, false, false, 0);
$pdf->Ln();
$pdf->SetFont('Times', '', 10);
//html table with the processed records goes here
$table ='<table width="555" style="border:1px solid black;" align="center">
//table contents
</table>';
$pdf->writeHTML($table, true, false, false, false, '');
$pdf->Ln();
$pdf->Ln();
//------------------------------------------------------------------------------------
//html table
$table ='<table width="540" align="center" style="border:1px solid black;">
//table contents
</table>';
$pdf->writeHTML($table, true, false, false, false, '');
//------------------------------------------------------------------------------------
$pdf->Ln();
$pdf->Ln();
//adding some text content to the pdf
$pdf->Write(0, 'Note:The information provided to you is confidential do not share it with others', '', 0, 'L', true, 0, false, false, 0);
$pdf->lastPage();
}
$pdf->Output('unnamed.pdf', 'I');
You can try to process only some row at time and then force output with ob_flush function (http://it1.php.net/ob_flush)
eg:
$chunk =0 ;
for($rows as $k => $v) {
$data_to_write = process_elem($k,$v);
write_to_pdf($data_to_write);
if($chunk++ == 50) {
ob_flush;
$chunk=0;
}
}
If you post your code I can help you in a better way.
Use a work queue such as Beanstalk. Instead of trying to work through all of the records at once, get the basic record id's from the main page. In the worker process, which will process one record at a time in in the background to actually assemble the PDF. Your initial script finishes quicker and you can monitor the queue in realtime. Your system will get through the records no matter how many you throw at it.
Beanstalk: http://kr.github.io/beanstalkd/
You will need the PHP library to use it: https://github.com/pda/pheanstalk
Once you get it, you can offload many background tasks with it such as logging, sending messages or image resize tasks to name a few of the workers I have setup.
Good Luck!

TCPDF: HTML table and page breaks

I am creating a large HTML table and I have problem with page breaks as you can see in the following image:
Is there a method settle down the problem automatically? Or what is the way to do it?
Try adding this to your <tr> tags: nobr="true".
So a quick example would be:
<table>
<tr nobr="true">
<td>Test</td>
<td>Test 2</td>
</tr>
</table>
The nobr="true" prevents the table rows from ever breaking apart. You can also put this on <td> and <th> tags.
I know it's rather old question, but I had this same issue today, my table was splitted between pages and I investigated a little bit further on the method from FastTrack's answer and it turned out that you can also use the nobr="true" attribute also to the <table> tag. That is, for me such code solved this problem:
<table nobr="true">
<tr>
<td>Test</td>
<td>Test 2</td>
</tr>
</table>
Warning - this code makes sense only when your tables are smaller than one page.
I had the same problem with overlapping headers.
I tried yevgeny solution, but that required some more editions to my PDF generator code (I have lots of PDFs outputs written in FPDF and I wanted to minimize the process of miograting them to TCPDF), so I used this more simple solution
class MYPDF extenfs TCPDF {
//your initialization code
function header(){
//your code here
//we change only the top margin and this executes for every header in every page, even the frst one
$this->SetTopMargin($this->GetY());
}
}
roney, thank you so much, writing HTML generated overlaps with the header for pages 2,3 .. this worked for me:
class your_PDF extends TCPDF
{
var $top_margin = 20;
function Header() {
// set top margin to style pages 2, 3..
//title goes here
$this->top_margin = $this->GetY() + 5; // padding for second page
}
}
in your code
// set top margin to style pages 2, 3..
$pdf->SetMargins(15, $pdf->top_margin, 15);
For the interested, just do as follows and it will work like a charm:
$pdf->SetMargins(0, 0, 0);
$pdf->SetHeaderMargin(0);
$pdf->SetFooterMargin(0);
Strangely enough the solutions mentioned here didn't work for me. Well, it did sortof, but content inside of tags would get repeated (as desired) but would then cause layout issues for the cell above or below if it was rowspanned. As I experimented, it just got worse.
My solution, while inelegant, was to set AutoPageBreak to false, put a row incrementer counter up, incrementing for each row, then checked if it had exceeded a certain value. If so, I closed the table, used writeHTML(), called addPage() and then continued , having rebuilt it as a new table, headers and all.
Like I said, inelegant, but it worked. I hope this helps someone ... it's a fairly obvious solution but execution is not always quite so obvious. Also, there may be a better way that works for your particular situation, but if it doesn't, give mine a try. :)
Some CSS solved for me:
// Include the main TCPDF library (search for installation path).
require_once('tcpdf/tcpdf.php');
// create new PDF document
$pdf = new TCPDF('R', PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
// set document information
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetAuthor('Author');
$pdf->SetTitle('TCPDF HTML Table');
$pdf->SetSubject('TCPDF Tutorial');
$pdf->SetKeywords('TCPDF, PDF, html,table, example, test, guide');
// set default header data
$pdf->SetHeaderData('', '', ' HTML table', '');
// 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(15, 15, 15);
$pdf->SetHeaderMargin(15);
$pdf->SetFooterMargin(15);
// set auto page breaks
$pdf->SetAutoPageBreak(TRUE, 15);
// set image scale factor
//$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
// ---------------------------------------------------------
// set font
$pdf->SetFont('times', '', 10);
// add a page
$pdf->AddPage();
$start = 1;
$end = 254;
$step = 1;
$arr = range($start, $end, $step);
$table_header .= sprintf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>", 'IP', 'Computer', 'User', 'Fone');
foreach ($arr as $ar) {
$row[] = $ar;
}
foreach ($row as $r):
if (($r % 40) === 0):
$table_header;
endif;
$table .= sprintf("<tr>\n<td>%s</td>\n<td>%s</td>\n<td>%s</td>\n<td>%s</td>\n</tr>\n", $r, $r, $r, $r);
endforeach;
$now = date("d/m/Y");
$caption = "<caption>IP addresses <em>$now</em></caption>\n";
$n = "\n";
$tbl = <<<EOD
<style>
table{
font-family: serif;
font-size: 11pt;
}
table tr {
}
table tr td {
padding:3px;
border:#000000 solid 1px;
}
em {
font-size: 4pt;
}
tr { white-space:nowrap; }
</style>
<h1>{$caption}</h1>
{$table_begin}
{$table_header}
{$table}
</table>
EOD;
$pdf->writeHTML($tbl, true, false, false, false, '');
// reset pointer to the last page
//$pdf->lastPage();
// ---------------------------------------------------------
//Close and output PDF document
$pdf->Output('html_table.pdf', 'I');
//============================================================+
// END OF FILE
//============================================================+
have you tried
<table>
<thead>
<tr>
<td>
This is my header which appears on every page
</td>
</tr>
</thead>
<tr>
<td>
My Content
</td>
</tr>
</table>
I'm using smarty, with this you have more possibilities to manually break the table (e.g. if you're using borders). If needed, i'll post this, too...

how to write barcode in html format when using tcpdf

I am using TCPDF to generate PDF file using following command
$pdf->writeHTML($htmlcontent, true, 0, true, 0);
TCPDF also provides a way to create barcode with following commands
$pdf->Cell(0, 0, 'C39+', 0, 1);
$pdf->write1DBarcode('Code 39', 'C39+', '', '', 80, 15, 0.4, $style, 'N');
$pdf->Ln();
I want to be able to write barcode as part of the HTML code above. Is there easy way?
I can potentially call a barcode image inthe writeHTML code above, but not sure how to use above barcode function (or any in TCPDF) which would allow me to create image and then get that image into HTML generation.
You can write TCPDF Methods in HTML as below
<?php
$params = $pdf->serializeTCPDFtagParameters(array('40144399300102444888207482244309', 'C128C', '', '', 0, 0, 0.2, array('position'=>'S', 'border'=>false, 'padding'=>4, 'fgcolor'=>array(0,0,0), 'bgcolor'=>array(255,255,255), 'text'=>false, 'font'=>'helvetica', 'fontsize'=>8, 'stretchtext'=>2), 'N'));
$str='<table cellspacing="0" cellpadding="1" border="0">
<tr>
<td align="left">barcode</td>
</tr>
<tr>
<td align="center" style="padding-left:5px;">';
$str .= '<tcpdf method="write1DBarcode" params="'.$params.'" />';
$str .='</td>
</tr>
</table>';
$pdf->writeHTML($str,true, false,false,false,'left');
$pdf->Output('example_049.pdf', 'I');
?>
For detail reference please check TCPDF example_049.php
TCPDF barcode classes already contains methods to export barcodes in various formats (SVG, PNG and HTML).
2D example:
require_once(dirname(__FILE__).'/2dbarcodes.php');
$barcodeobj = new TCPDF2DBarcode('http://www.tcpdf.org', 'QRCODE,H');
// export as SVG image
//$barcodeobj->getBarcodeSVG(3, 3, 'black');
// export as PNG image
//$barcodeobj->getBarcodePNG(3, 3, array(0,128,0));
// export as HTML code
echo $barcodeobj->getBarcodeHTML(3, 3, 'black');
1D example:
require_once(dirname(__FILE__).'/barcodes.php');
$barcodeobj = new TCPDFBarcode('123456', 'C128');
// export as SVG image
//$barcodeobj->getBarcodeSVG(2, 30, 'black');
// export as PNG image
//$barcodeobj->getBarcodePNG(2, 30, array(0,128,0));
// export as HTML code
echo $barcodeobj->getBarcodeHTML(2, 30, 'black');
Check the documentation and examples at http://www.tcpdf.org for further information.
You could put your barcode number is a fake HTML tag and then parse for that tag as you write out the HTML like in this example.
This would be in your HTML:
some HTML.... <POSTNET>12345-1234</POSTNET> ....some more HTML
This is the code to parse for the fake tag.
// look to see if there is a POSTNET tag
if (strpos($letter_html, "<POSTNET>") !== false) {
$postnet_pre = explode("<POSTNET>", $letter_html);
$this->WriteHTML($postnet_pre[0], $this->line_height);
// write the barcode
$postnet_post = explode("</POSTNET>", $postnet_pre[1]);
$zip_code = $postnet_post[0];
$this->write1DBarcode($zip_code, 'POSTNET', '', '', 80, 15, 0.4, $style, 'N');
// write rest of the letter
$this->WriteHTML($postnet_post[1], $this->line_height);
} else {
// no POSTNET so just write the whole letter
$this->WriteHTML($letter_html, $this->line_height);
}
When generating a barcode, make sure that you enclose the 12-digit delivery point inside of the "slash" character. Most POSTNET fonts render the slash character as the "control" character that pre/post-fixes the barcode values. Without those control characters the barcode isn't technically valid.
The POSTNET barcode font in TrueType format can be downloaded.
I tried the following and it worked:
$params = $pdf->serializeTCPDFtagParameters(
array('https://tcpdf.org/', 'QRCODE,H', '', '', 27, 27, '', 'N')
);
$html .= '<tcpdf method="write2DBarcode" params="'.$params.'" />';

Categories