10

I am using PHP and FPDF to generate a PDF with a list of items. My problem is if the item list goes on to a second or third page, I want to keep the Item Name, Quantity and Description together. Right now, it will go to a second page, but it may split up all of the details for a particular item. PLEASE HELP!

<?php
require_once('auth.php');      
require_once('config.php');   
require_once('connect.php');  

$sqlitems="SELECT * FROM $tbl_items WHERE username = '" . $_SESSION['SESS_LOGIN'] . "'";
$resultitems=mysql_query($sqlitems);

require_once('pdf/fpdf.php');
require_once('pdf/fpdi.php');


$pdf =& new FPDI();
$pdf->AddPage('P', 'Letter');    
$pdf->setSourceFile('pdf/files/healthform/meds.pdf'); 
$tplIdx = $pdf->importPage(1);
$pdf->useTemplate($tplIdx);

$pdf->SetAutoPageBreak(on, 30);

$pdf->SetTextColor(0,0,0);
$pdf->Ln(10);

while($rowsitems=mysql_fetch_array($resultitems)){

$pdf->SetFont('Arial','B',10);
$pdf->Cell(50,4,'Item Name:',0,0,'L');
$pdf->SetFont('');
$pdf->Cell(100,4,$rowsitems['itemname'],0,0,'L');  

$pdf->SetFont('Arial','B',10);
$pdf->Cell(50,4,'Quantity:',0,0,'L');
$pdf->SetFont('');
$pdf->Cell(140,4,$rowsitems['itemqty'],0,1,'L');

$pdf->SetFont('Arial','B');
$pdf->Cell(50,4,'Description:',0,0,'L');
$pdf->SetFont('');
$pdf->Cell(140,4,$rowsitems['itemdesc'],0,1,'L');
}

$pdf->Output('Items.pdf', 'I');

?>
Michael
  • 2,276
  • 15
  • 49
  • 80

3 Answers3

13

bmb is on the right track. Here is a little more detailed solution.

There are a number of different ways to do this, but you'll have to make some decisions based on what you want. If you have rows that may take up half the page, then this probably isn't going to work the best for you, but if your rows are typically about 2 - 5 lines long then this is a good method.

Because my first cell in the row is a multiple lined cell (MultiCell in FPDF speak) in my table, the rows are of dynamic height based on this first cell. So I figure out how high the row is going to be based on the string width and the width of the cell and then compare that with the room left on the page, based on the current Y position, the page height and the bottom margin:

while ($row = mysql_fetch_array($result)) {

  // multicell content
  $description = $row['desciption'];

  // get column width from a column widths array
  $column_width = $column_widths['description'];

  $number_of_lines = ceil( $pdf->GetStringWidth($description) / ($column_width - 1) );
  // I subtracted one from column width as a kind of cell padding

  // height of resulting cell
  $cell_height = 5 + 1; // I have my cells at a height of five so set to six for a padding
  $height_of_cell = ceil( $number_of_lines * $cell_height ); 

  // set page constants
  $page_height = 279.4; // mm (portrait letter)
  $bottom_margin = 20; // mm

  // mm until end of page (less bottom margin of 20mm)
  $space_left = $page_height - $pdf.GetY(); // space left on page
  $space_left -= $bottom_margin; // less the bottom margin

  // test if height of cell is greater than space left
  if ( $height_of_cell >= $space_left) {
     $pdf->Ln();                        

     $pdf->AddPage(); // page break.
     $pdf->Cell(100,5,'','B',2); // this creates a blank row for formatting reasons
  }

  // ...
  // actual creation of pdf stuff
  // ...

}
Joshua Pinter
  • 45,245
  • 23
  • 243
  • 245
5

It seems like you have a few options.

You can keep track of where you are on the page as you go through your loop, and issue your own page break when you run out of space. This requires that you use SetAutoPageBreak() to turn off auto page breaks.

Another method is to override the AcceptPageBreak() method. That method is called automatically when a page break will be added. You would want to return FALSE if you want to squeeze another line onto the current page, so you would have to keep track of which detail you're currently printing.

bmb
  • 6,058
  • 2
  • 37
  • 58
-1

What about the "page-break-inside" property? I tried it inside a table and it helps.

I hardcoded "page-break-inside" in-line css property to my row and this row didn't break anymore when it was sent to printing pages, spreading across two pages. It was pushed either completely to the new page or left on the previous. Maybe it is not a dynamic fix (from the fPDF side of things), but it still resolves the issue.

  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post - you can always comment on your own posts, and once you have sufficient reputation you will be able to comment on any post. – Kevin Dec 29 '14 at 07:33
  • Actually it did provide the solution in my case. Adding "page-break-inside" in-line css property to the row, or table, keeps this row/table from breaking when it is sent to the printer pages and spreads across the two pages. It is at least a hardcoded fix, if not dynamic from the fPDF side. – Gordan Karabogdan Jan 13 '15 at 12:06