generating data from db in tcpdf table - php

I am trying to generate pdf with database values using tcpdf.
I have a function to fetch data like this
function fetch_data()
{
$output = '';
include('../connection.php');
// Colors, line width and bold font
//My sql
$sql ="";
$query = mysqli_query($con, $sql) or die (mysqli_error($con));
$total_amt = 0;
$tax_amt = 0;
while($row = mysqli_fetch_array($query)) {
$output .= '<tr>
<td style="border-bottom:1px thin #666; font-size:12px; font-weight:normal; font-style:normal;">'.$row["product"].' - '.$row['description'].'</td>
<td style="border-bottom:1px thin #666"; align="center">'.$row["uom"].'</td>
<td style="border-bottom:1px thin #666"; align="center">'.$row["price"].'</td>
<td style="border-bottom:1px thin #666"; align="center">'.$row["qty"].'</td>
<td style="border-bottom:1px thin #666"; align="center">'.$row["discount"].'</td>
<td style="border-bottom:1px thin #666"; align="center">'.$row["taxation"].'%</td>
<td style="border-bottom:1px thin #666"; align="center">'.$row["total"].'</td>
</tr>
';
$total_amt += $row['total'];
$tax_amt += $row['tax_amount'];
}
$output .= '<tr><td colspan="7" style="border-top:1px thin #666";></td></tr><tr><td colspan="5" align="left"><strong>Total</strong></td><td align="center">'.number_format($tax_amt,2).'</td><td align="center">'.number_format($total_amt,2).'</td></tr>';
return $output;
}
And i display it
$content = '';
$content .= '
<table border="1"><tr><td width="100%">
<table border="0">
<tr bgcolor="#796799" style="color:#FFF;">' ;
$pdf->SetFont('arsenalb', 'B', 12);
$content .= '
<th width="40%" style="border-left-width:14px;border-left-color:#796799;" height="30" align="center">Description</th>
<th width="10%" align="center">UOM</th>
<th width="13%" align="center">Price</th>
<th width="7%" align="center">Qty</th>
<th width="7%" align="center">Disc</th>
<th width="10%" align="center">Tax</th>
<th width="13%" align="center">Total</th>
</tr>
';
$pdf->SetFont('arsenal', '', 10);
$content .= fetch_data();
$content .= '</table></td></tr></table>';
$pdf->writeHTML($content);
I want only the table headers to be bold, so i have used $pdf->SetFont('arsenal', '', 10); after the header . But it is making the header also normal, not bold. if i remove this, then whole table data is becoming bold.
is there any way to separate the table something like this? https://tcpdf.org/examples/example_011/

The reason this wont work is quite simpel. You write all $content to the $pdf AFTER the second SetFont line. Meaning that the first line is used, but since no content is added to the pdf, it wont show anything.
Since tcpdf allows you to write HTML, wyy not use HTML to make the header bold? with the <b> tag. Another option is that you make two tables. One for the header and one for the content. Since you define the width of the columns, you can do this.
You'll get something like:
$hdr = 'full table with header data';
$pdf->SetFont('arsenalb', 'B', 12);
$pdf->writeHTML($hdr);
$content .= 'new table, with column with defined';
$content .= fetch_data();
$content .= '</table></td></tr></table>';
$pdf->SetFont('arsenal', '', 10);
$pdf->writeHTML($content);
but that might work depending on if you need that second outer table. If you need it, it will most likely not possilbe, unless you can write partial HTML yo $pdf->writeHTML(). I'm not sure you can/cannot.

Related

TCPDF table header automatically move to the right

I have created a table with TCPDF. The header, which has a black background, has been positioned slightly to the right as though there is some padding on the left hand side. I cannot get it to line up correctly.
The code below is the HTML I have written to form the table.
$tbl ='<style>
th {background-color: black;color: white;float:left;}
.tal {text-align: left;float:left;}
</style>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<th width="60px" style="border-right: 1px solid white;"><strong>Qty</strong></th>
<th width="1px"></th>
<th class="tal" width="388px" style="padding:10px 0; border-right: 1px solid white;"> <strong>Product or Service</strong></th>
<th width="1px"></th>
<th width="84px" style="border-right: 1px solid white;"><strong>Price Each</strong></th>
<th width="1px"></th>
<th width="84px"><strong>Total</strong></th>
</tr>
<tr>
<td height="267px">';
while($i <= $a) {
$tbl .= '<table height="267px" width="60px"><tr><td>' . $productsArray['product_quantity'][$i] . '</td></tr></table>';
$i++;
}
$tbl .= '</td><td border="1" width="0.5px" height="267px" style="background:url(images/bars-black.jpg) bottom right no-repeat"></td><td height="267px">';
while($j <= $a) {
$tbl .= '<table height="267px" width="388px"><tr><td class="tal"> ' . $productsArray['product_name'][$j] . '</td></tr></table>';
$j++;
}
$tbl .= '</td><td width="0.5px" height="267px" style="background:url(images/bars-black.jpg) bottom right no-repeat"></td><td height="267px">';
while($k <= $a) {
$tbl .= '<table height="267px" width="84px"><tr><td>' . $productsArray['product_price'][$k] . '</td></tr></table>';
$k++;
}
$tbl .= '</td><td border="1" width="0.5px" height="267px" style="background:url(images/bars-black.jpg) bottom right no-repeat"></td><td height="267px">';
while($l <= $a) {
$tbl .= '<table height="267px" width="84px"><tr><td>' . $productsArray['product_sub'][$l] . '</td></tr></table>';
$l++;
}
$tbl .= '</td>
</tr>
</table>';
}
The below code is the PHP I have used to show the table on the page.
$pdf->writeHTMLCell(175, 80, 20, 100, $tbl, 1, 1, 0, true, 'C', true);
Using tables within cells of another table is generally a really bad idea and is likely contributing to the problem you are having. Since it looks like your productsArray already has all of the data you need I would simply loop through it outputting each row as you go.
It's also worth pointing out that the empty header rows that are defined with a width of 1px conflict with your actual data rows which are defined with a width of 0.5px.
<style>
th {background-color: black;color: white;float:left;}
.tal {text-align: left;float:left;}
</style>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<th width="60px" style="border-right: 1px solid white;"><strong>Qty</strong></th>
<th width="1px"></th>
<th class="tal" width="388px" style="padding:10px 0; border-right: 1px solid white;"> <strong>Product or Service</strong></th>
<th width="1px"></th>
<th width="84px" style="border-right: 1px solid white;"><strong>Price Each</strong></th>
<th width="1px"></th>
<th width="84px"><strong>Total</strong></th>
</tr>
<?php
while($i <= $a) {
?>
<tr>
<td height="267px"><?php echo $productsArray['product_quantity'][$i]; ?></td>
<td border="1" width="0.5px" height="267px" style="background:url(images/bars-black.jpg) bottom right no-repeat"></td>
<td height="267px"><?php echo $productsArray['product_name'][$i]; ?></td>
<td width="0.5px" height="267px" style="background:url(images/bars-black.jpg) bottom right no-repeat"></td>
<td height="267px"><?php echo $productsArray['product_price'][$i]; ?></td>
<td border="1" width="0.5px" height="267px" style="background:url(images/bars-black.jpg) bottom right no-repeat"></td>
<td height="267px"><?php echo $productsArray['product_sub'][$l]; ?></td>
</tr>
<?php
$i++;
}
?>
</table>

TCPDF manual page break

I am working on invoice printout.
I am facing a problem in printing the invoice. let's say there is an invoice that consist of items that are exactly in 1 page. The problem is there are subtotal, tax, and grandtotal after all the items.
In this case these 3 would be on the second page(new page), while the items are on 1st page.
I have done checking the row that one page can hold in tcpdf(after all my layout format, etc) and found out 1 page will consist of 28 items. This will work well if all the item consists of 1 row. However, if some of the items consist of 2 or more rows, the calculation will face a problem, and the whole structure will be a mess.
How can i automatically move some items to second page if the total items are 28 items, so the second page will not only consist of the subtotal, tax, and grand total?
here is my code
$count = 0;
$i = 0;
if(count($finalProduct)>0){
foreach($finalProduct as $product){
foreach($product['product'] as $prod){
if($prod['qty'] > 0){
/* check the row */
if($count >= 27){
$PDFCONTENT .= '<tr style="page-break-after:initial"><td colspan="6"></td></tr>';
$PDFCONTENT .= '<tr><td colspan="6"></td></tr>';
$count = 0;
}
$PDFCONTENT .= '
<tr nobr="true">';
$PDFCONTENT .= '<td align="center" width="7%">'.$prod['index_number'].'</td>';
</tr>';
}
$count++;
}
$PDFCONTENT .= '<tr><td></td></tr>';
}
}
$PDFCONTENT .= '<tfoot>
<tr> <td> </td> </tr>
<tr>
<th align="right" colspan="6">SUB TOTAL $:-</th>
<th style="border-top: 1px solid black;border-bottom: 1px solid black;" align="center">'.number_format($data['total'],2).'</th>
</tr>
<tr>
<th align="right" colspan="6">ADD '.number_format($data['transaction_tax_percentage']).'% $:-</th>
<th style="border-top: 1px solid black;border-bottom: 1px solid black;" align="center">'.number_format($data['transaction_tax_amount'],2).'</th>
</tr>
<tr>
<th align="right" colspan="6">TOTAL $:-</th>
<th style="border-top: 1px solid black;border-bottom: 1px solid black;" align="center">'.number_format($data['grand_total'],2).'</th>
</tr>
</tfoot>';
I remember that this was a real problem with tables. so we calculatet if there is a pagebreak to be set. If so, we closed the tabel, added a new site and reopened the table and put the rest of the table in it.
To force the pagebreak we used <br pagebreak="true"/>
if you don't close the table it leads to other problems.
A good threat is also here on SO: Manual Page Break in TCPDF

TCPDF ImageSVG dynamic position in writeHTMLCell

I am creating a pdf using TCPDF and everything is rendering the way that I want it. There is an area that is dynamic where it writes a variable number of lines. This area is rendered using writeHTMLCell. After this is rendered I want to place a signature image using $pdf->ImageSVG in the area marked '{SIGNATURE HERE}'. What are the dynamic coordinates based on variable lines ahead of it to place it in the correct position.
Thank you for any help.
$tbl = '<p>It is hereby requested that you prepare for use on (check one) ';
if($appeal_non=='appeal') {
$tbl .= ' <u>[X] appeal</u> [ ]non-appeal* ';
}else{
$tbl .= ' [ ]appeal <u>[X] non-appeal*</u> ';
}
$tbl .= ' an original and <u>'.$quant.'</u> copies of the following:</p>';
$tbl .='<table cellspacing="0" cellpadding="1" border="0" >
<tr>
<td>DATE OF PROCEEDING</td>
<td>TYPE OF PROCEEDING <br />(e.g., trial, sentencing, motion, etc.)</td>
<td>NAME OF JUDGE</td>
</tr>';
$p=0;
foreach($proc_date as $proc){
$tbl .= '<tr>
<td>'.$proc.'</td>
<td>'.$proc_type[$p].'</td>
<td>'.$proc_judge[$p].'</td>
</tr>';
$p = $p + 1;
}
$tbl .= '</table>
<p>I agree to pay for the preparation and any copies ordered of the transcript(s) for the above date(s) pursuant to R. 2:5-3(d).</p>
<table cellspacing="0" cellpadding="1" border="0" >
<tr>
<td><p> <br />{SIGNATURE HERE}<br/> </p></td>
<td>'.$sig_date.'</td>
</tr>
<tr>
<td><hr />SIGNATURE OF REQUESTING PARTY</td>
<td><hr />DATE</td>
</tr>
</table>
<p>Transcript fees are set by New Jersey Statute 2B:7-4. An additional sum or reimbursement may be required prior to or at the
completion of the transcript order.</p>
<p style="text-align:center;">DEPOSIT ATTACHED: $<u>'.$depositAmount.'</u></p>
';
$pdf->writeHTMLCell(0, '', '', '', $tbl, 1, 1, false, true, 'L', true);
$tbl = '<table cellspacing="0" cellpadding="1" border="0" >
<tr>
<td colspan="2">* Only the Supervisor of Court Reporters should receive copies of non-appeal transcript requests.</td>
</tr>
<tr>
<td width="5%">CC:</td>
<td width="95%">1. CLERK, Appellate Division, or CLERK, Supreme Court (see INSTRUCTIONS above)</td>
</tr>
<tr>
<td width="5%"></td>
<td width="95%">2. County Supervisor of Court Reporters _______</td>
</tr>
<tr>
<td width="5%"></td>
<td width="95%">3. Other attorneys/<span style="border-bottom: 1px solid;">Pro</span> <span style="border-bottom: 1px solid;">Se</span> parties _________</td>
</tr>
</table>';
//$sigY = $pdf->SetY($sigY);
$pdf->writeHTMLCell(0, '', '', '', $tbl, 1, 1, false, true, 'L', true);
//$sigY = $pdf->GetY();
//$sigY2 = $sigY - 40.2;
//$pdf->writeHTMLCell(0, '', '', '', '<p>'.$sigY.'<p>', 1, 1, false, true, 'L', true);
$pdf->ImageSVG($file='#'.$sig_code, $x='', $y='$sigY2', $w='80', $h='50', $link='', $align='B', $palign='L', $border=0, $fitonpage=true);

mixing html code with php code

I am trying to use tcpdf library to generate pdf. I have a php file which contains variables like name,company name etc. But for displaying the products I am passing the array to php. Now I want to display each element of array in a table row for that I have to write the php code but somehow I am having problem mixing PHP code with html code.Here is the part whihch contains the problem
$html .= '<br><br>
<table border="1" cellpadding="5">
<tr>
<td colspan="3">Invoice # {invoice_ref_id}</td>
</tr>
<tr>
<td><b>Product</b></td>
<td><b>Quantity</b></td>
<td align="right"><b>Amount (Rs.)</b></td>
</tr>'.
foreach($item as products): .' //This part contains error
<tr>
<td>'echo products['item']'</td>
<td>'echo products['quantity']'</td>
<td align="right">75</td>
</tr>
<tr>
<td colspan="3" align="right"><b>Total: 375</b></td>
</tr>'
endforeach;
'</table>';
$html .= '<br><br>Some more text can come here...';
Instead of concatenating your HTML in a string that you will then need to echo, I would go to something like this :
<br><br>
<table border="1" cellpadding="5">
<tr>
<td colspan="3">Invoice # {invoice_ref_id}</td>
</tr>
<tr>
<td><b>Product</b></td>
<td><b>Quantity</b></td>
<td align="right"><b>Amount (Rs.)</b></td>
</tr>
<?php foreach($item as products){ ?>
<tr>
<td><?php echo products['item'] ?></td>
<td><?php echo products['quantity'] ?></td>
<td align="right">75</td>
</tr>
<tr>
<td colspan="3" align="right"><b>Total: 375</b></td>
</tr>
<?php> } //ending the foreach ?>
</table>
<br><br>Some more text can come here...
Notice how even here HTML code is still correctly highlighted? It will probably be the same in your editor of choice. I find it much more readable, and you even avoid possible character escaping issues.
NOTE : I didn't fix your HTML, but there are several bad practices in it regarding semantics or even use of obsolete/deprecated tags. Here are a few:
Don't use anything changing layout in your HTML, this is what CSS are for. For example, don't use border or cellpadding attributes on your table, use table {border: 1px solid #ccc;} (you can of course change color, that's an example) and table td {padding: 5px;} instead.
Semantic best practices also imply not using <br> tag. Better define top or bottom margins to put some space between elements. (I must admit that's probably the only example where I value ease over semantic and sometimes use it myself though)
<b> tag should be use only in very specific cases, cfr this article. In this specific case you can achieve the same effect (bold text) by using font-weight: bold on the desired cells, either by giving them a specific CSS class, either by targetting them with a CSS selector like for example : tr td:nth-child(3) {font-weight: bold;}}
similarily, don't use align attribute, same thing, target the desired cell and use CSS property text-align: right; instead.
You can't continue the html with a concatenation straight after the foreach. You have to do $html .= again.
This
</tr>'.
foreach($item as products): .' //This part contains error
<tr>
should be this
</tr>';
foreach($item as products): $html .= ' //This part contains error
<tr>
The same goes at the end of the foreach:
</tr>';
endforeach;
$html .= '</table>';
You are doing it wrong way. This should work -
$html .= '<br><br>
<table border="1" cellpadding="5">
<tr>
<td colspan="3">Invoice # {invoice_ref_id}</td>
</tr>
<tr>
<td><b>Product</b></td>
<td><b>Quantity</b></td>
<td align="right"><b>Amount (Rs.)</b></td>
</tr>';
foreach($item as products) { //This part contains error
$html .= '<tr>
<td>'. products['item']. '</td>
<td>'. products['quantity']. '</td>
<td align="right">75</td>
........ ';
}
$html .= '</table>';
$html .= '<br><br>Some more text can come here...';
thie right way of doing something like this
$html .= '<br><br>
<table border="1" cellpadding="5">
<tr>
<td colspan="3">Invoice # {invoice_ref_id}</td>
</tr>
<tr>
<td><b>Product</b></td>
<td><b>Quantity</b></td>
<td align="right"><b>Amount (Rs.)</b></td>
</tr>';
foreach($item as products):
$html .=' //This part contains error
<tr>
<td>'echo products['item']'</td>
<td>'echo products['quantity']'</td>
<td align="right">75</td>
</tr>
<tr>
<td colspan="3" align="right"><b>Total: 375</b></td>
</tr>';
endforeach;
$html .= '</table>';
$html .= '<br><br>Some more text can come here...';

Displaying message outside of while loop

I have some working code where a directory is scanned and the PDF file results placed in a table. However, what I cannot seem to do is if there are no results then display a message in the table outside the while loop. Can someone help with this. Thanks
<?php
// WHAT IS IN THE STORAGE DIRECTORY
$sub = 'destcerts' . '/' . $_SESSION['kt_idcode_usr'];
// READ THE NAMES OF FILES IN THE SUB-DIRECTORY
$fff = new DirectoryIterator($sub);
$sss = array();
foreach ($fff as $filedata)
{
// SKIP THE "DOT" FILES
if ($filedata->isDot()) continue;
// ACTIVATE THIS LINE TO RESTRICT IT TO PDF FILES ONLY
if ($filedata->getExtension() != 'pdf') continue;
// CREATE LINKS TO THESE FILES
$nom = $filedata->getFilename();
$value = substr ($nom, 0, 4);
//$_SESSION['value'] = $value;
if($_SESSION['kt_idcode_usr'] == $value) {
$lnk
= '<img src="destcerts/PDF_icon_100.png" style="margin-bottom: 15px; margin-top:15px;"><br /><a href="'
. $sub
. '/'
. $nom
. '" style="color:#0099FF; text-decoration:none; font-size:12px; font-family: Verdana, Geneva, sans-serif;">'
. $nom
. '</a>'
;
}
// COLLECT THE LINKS HERE
$sss[] = $lnk;
}
// ACCUMULATE THE TABLE ROWS HERE
$trs = NULL;
// COLLECT GROUPS OF FOUR
while (!empty($sss))
{
$td1 = array_shift($sss) or NULL;
$td2 = array_shift($sss) or NULL;
$td3 = array_shift($sss) or NULL;
$td4 = array_shift($sss) or NULL;
// USE HEREDOC TO INSERT THESE INTO A TABLE ROW
$tr = <<<EOD
<tr>
<td align="center" width="20%" style="padding-bottom:20px !important;">$td1</td>
<td align="center" width="20%" style="padding-bottom:20px !important;">$td2</td>
<td align="center" width="20%" style="padding-bottom:20px !important;">$td3</td>
<td align="center" width="20%" style="padding-bottom:20px !important;">$td4</td>
</tr>
EOD;
// APPEND THE TABLE ROW TO THE OTHER ROWS
$trs .= $tr;
}
// USE HEREDOC TO INSERT THE TABLE ROWS INTO THE TABLE
$tab = <<<EOD
<table id="pdfDownload" width="94%" align="center" border="1" cellspacing="10" cellpadding="0" style="border:1px solid grey; padding-bottom: 10px; margin-bottom:20px;">
<th style="text-align:center; padding: 10px !important; padding-bottom: 20px; border:1px solid black; background-color: #3399FF; color: white; font-size: 18px !important;" colspan="4">Destruction Certificates Download</th>
<tr>
<th style="text-align:center; padding-top: 10px !important;"></th>
<th></th>
<th></th>
<th></th>
</tr>
$trs
</table>
EOD;
// SHOW THE WORK PRODUCT
echo $tab;
?>
Try enclosing the WHILE LOOP in a IF statement to verify if there is anything to loop.
If(!empty($sss)){
while (!empty($sss))
{
$td1 = array_shift($sss) or NULL;
$td2 = array_shift($sss) or NULL;
$td3 = array_shift($sss) or NULL;
$td4 = array_shift($sss) or NULL;
// USE HEREDOC TO INSERT THESE INTO A TABLE ROW
$tr = <<<EOD
<tr>
<td align="center" width="20%" style="padding-bottom:20px !important;">$td1</td>
<td align="center" width="20%" style="padding-bottom:20px !important;">$td2</td>
<td align="center" width="20%" style="padding-bottom:20px !important;">$td3</td>
<td align="center" width="20%" style="padding-bottom:20px !important;">$td4</td>
</tr>
EOD;
// APPEND THE TABLE ROW TO THE OTHER ROWS
$trs .= $tr;
}
}
else{
$msg = " Put some message to display that there are no files to display ";
$tr = <<<EOD
<tr>
<td align="center" colspan="4" style="padding-bottom:20px !important;">$msg</td>
</tr>
EOD;
$trs .= $tr;
}

Categories