Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FPDF Page Break Question

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

?>
like image 318
Michael Avatar asked Mar 12 '10 01:03

Michael


2 Answers

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
  // ...

}
like image 54
Joshua Pinter Avatar answered Oct 08 '22 01:10

Joshua Pinter


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.

like image 39
bmb Avatar answered Oct 08 '22 01:10

bmb