Table with MultiCells

Informations

Author: Olivier
License: FPDF

Description

The goal of this script is to show how to build a table from MultiCells.
As MultiCells go to the next line after being output, the base idea consists in saving the current position, printing the MultiCell and resetting the position to its right.
There is a difficulty, however, if the table is too long: page breaks. Before outputting a row, it is necessary to know whether it will cause a break or not. If it does overflow, a manual page break must be done first.
To do so, the height of the row must be known in advance; it is the maximum of the heights of the MultiCells it is made up of. To know the height of a MultiCell, the NbLines() method is used: it returns the number of lines a MultiCell will occupy.

Source

<?php
require('fpdf.php');

class PDF_MC_Table extends FPDF
{
    protected $widths;
    protected $aligns;

    function SetWidths($w)
    {
        // Set the array of column widths
        $this->widths = $w;
    }

    function SetAligns($a)
    {
        // Set the array of column alignments
        $this->aligns = $a;
    }

    function Row($data)
    {
        // Calculate the height of the row
        $nb = 0;
        for($i=0;$i<count($data);$i++)
            $nb = max($nb,$this->NbLines($this->widths[$i],$data[$i]));
        $h = 5*$nb;
        // Issue a page break first if needed
        $this->CheckPageBreak($h);
        // Draw the cells of the row
        for($i=0;$i<count($data);$i++)
        {
            $w = $this->widths[$i];
            $a = isset($this->aligns[$i]) ? $this->aligns[$i] : 'L';
            // Save the current position
            $x = $this->GetX();
            $y = $this->GetY();
            // Draw the border
            $this->Rect($x,$y,$w,$h);
            // Print the text
            $this->MultiCell($w,5,$data[$i],0,$a);
            // Put the position to the right of the cell
            $this->SetXY($x+$w,$y);
        }
        // Go to the next line
        $this->Ln($h);
    }

    function CheckPageBreak($h)
    {
        // If the height h would cause an overflow, add a new page immediately
        if($this->GetY()+$h>$this->PageBreakTrigger)
            $this->AddPage($this->CurOrientation);
    }

    function NbLines($w, $txt)
    {
        // Compute the number of lines a MultiCell of width w will take
        if(!isset($this->CurrentFont))
            $this->Error('No font has been set');
        $cw = $this->CurrentFont['cw'];
        if($w==0)
            $w = $this->w-$this->rMargin-$this->x;
        $wmax = ($w-2*$this->cMargin)*1000/$this->FontSize;
        $s = str_replace("\r",'',(string)$txt);
        $nb = strlen($s);
        if($nb>0 && $s[$nb-1]=="\n")
            $nb--;
        $sep = -1;
        $i = 0;
        $j = 0;
        $l = 0;
        $nl = 1;
        while($i<$nb)
        {
            $c = $s[$i];
            if($c=="\n")
            {
                $i++;
                $sep = -1;
                $j = $i;
                $l = 0;
                $nl++;
                continue;
            }
            if($c==' ')
                $sep = $i;
            $l += $cw[$c];
            if($l>$wmax)
            {
                if($sep==-1)
                {
                    if($i==$j)
                        $i++;
                }
                else
                    $i = $sep+1;
                $sep = -1;
                $j = $i;
                $l = 0;
                $nl++;
            }
            else
                $i++;
        }
        return $nl;
    }
}
?>

Example

Here's an example of multi-page table with random content:
<?php
require('mc_table.php');

function GenerateWord()
{
    // Get a random word
    $nb = rand(3, 10);
    $w = '';
    for($i=1;$i<=$nb;$i++)
        $w .= chr(rand(ord('a'), ord('z')));
    return $w;
}

function GenerateSentence()
{
    // Get a random sentence
    $nb = rand(1, 10);
    $s = '';
    for($i=1;$i<=$nb;$i++)
        $s .= GenerateWord().' ';
    return substr($s, 0, -1);
}

$pdf = new PDF_MC_Table();
$pdf->AddPage();
$pdf->SetFont('Arial', '', 14);
// Table with 20 rows and 4 columns
$pdf->SetWidths(array(30, 50, 30, 40));
for($i=0;$i<20;$i++)
    $pdf->Row(array(GenerateSentence(), GenerateSentence(), GenerateSentence(), GenerateSentence()));
$pdf->Output();
?>
View the result here.

Download

ZIP | TGZ