How to put column headings of a table on each page in tcpdf?
Asked Answered
S

5

19

The code used to print the pdf is as follows:

class MYPDF extends TCPDF {

    // Load table data from file
    public function LoadData($file) {
        // Read file lines
        $lines = file($file);
        $data = array();
        foreach($lines as $line) {
            $data[] = explode(';', chop($line));
        }
        return $data;
    }

    // Colored table
    public function ColoredTable($header,$data) {
        // Colors, line width and bold font
        $this->SetFillColor(233, 136, 64);
        $this->SetTextColor(255);
        $this->SetDrawColor(128, 0, 0);
        $this->SetLineWidth(0.3);
        $this->SetFont('', 'B');
        // Header
        $w = array(10, 40, 20, 20, 20, 20, 20);
        $num_headers = count($header);
        for($i = 0; $i < $num_headers; ++$i) {
            $this->Cell($w[$i], 7, $header[$i], 1, 0, 'C', 1);
        }
        $this->Ln();
        // Color and font restoration
        $this->SetFillColor(224, 235, 255);
        $this->SetTextColor(0);
        $this->SetFont('');
        // Data
        $fill = 0;
        foreach($data as $row) {
            $this->Cell($w[0], 6, $row[0], 'LR', 0, 'C', $fill);
            $this->Cell($w[1], 6, $row[1], 'LR', 0, 'L', $fill);
            $this->Cell($w[2], 6, $row[2], 'LR', 0, 'C', $fill);
            $this->Cell($w[3], 6, $row[3], 'LR', 0, 'C', $fill);
            $this->Cell($w[4], 6, $row[4], 'LR', 0, 'C', $fill);
            $this->Cell($w[5], 6, $row[5], 'LR', 0, 'C', $fill);
            $this->Cell($w[6], 6, $row[6], 'LR', 0, 'C', $fill);
            $this->Ln();
            $fill=!$fill;
        }
        $this->Cell(array_sum($w), 0, '', 'T');
    }
}

// create new PDF document
$pdf = new MYPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);

// set document information
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetAuthor('Nicola Asuni');
$pdf->SetTitle('TCPDF Example 011');
$pdf->SetSubject('TCPDF Tutorial');
$pdf->SetKeywords('TCPDF, PDF, example, test, guide');

// set default header data
$pdf->SetHeaderData(PDF_GYANKUTIR_LOGO, PDF_HEADER_LOGO_WIDTH, 'GyanKutir', 
'Jhunjhunu International Wisdom City
Near Khemi Shakti Temple
Jhunjhunu (Rajasthan)-333001');

// 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(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER);
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER);

//set auto page breaks
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);

//set image scale factor
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);

//set some language-dependent strings
$pdf->setLanguageArray($l);

// ---------------------------------------------------------

// set font
$pdf->SetFont('helvetica', '', 6);

// add a page
$pdf->AddPage();

//Column titles
$header = array('Rank', 'Student', 'Time Used', 'Correct Answers', 'Wrong Answers','Questions Skipped','Final Score');


$final_data = $smarty->fetch($file_to_show);

$file = fopen("text.txt","w+");

    file_put_contents($file,"");
    fwrite($file,$final_data);
    fclose($file);

ob_start();
        ob_flush();
//Data loading
$data = $pdf->LoadData('text.txt');

// print colored table
$pdf->ColoredTable($header, $data);

// ---------------------------------------------------------
 ob_flush();
//Close and output PDF document
$pdf->Output('example_011.pdf', 'I');

//============================================================+
// END OF FILE                                                
//============================================================+

I want to add the headings to the table columns on each page. The screenshot is attached with this question. In the first screenshot the headings are getting displayed but in second screen shot the are not getting displayed. How to display those column headings on subsequent pages? Please help me out to resolve this issue. thanks in Advance.This image is the first page of a table in pdf.This is the first page of a table with proper headingsThis is the second page of a table where the headings should be displayed as of first page.

Saccharify answered 11/1, 2013 at 8:25 Comment(0)
M
13

Two methods come to my mind.

Method 1: Create your own custom header function (like in TCPDF example 3) that automatically adds the header cells to each page. In this scenario, you would move the header cell placement code into a Header method in your class and draw the headers to a fixed position on the page. Since the Header method is called automatically when a new page is added, your table headers would then be added as soon as the page is created. This is certainly faster and less intensive than method 2, but it can be a little tricky.

Method 2: Use TCPDF transactions to detect when a row is about to break the page, and then rollback. You would then AddPage yourself; draw the headers again; and continue with display. You can do this by getting the number of pages before you make the row, and comparing it to the number of pages after. An example of how you might do it this way as been provided:

    //Separated Header Drawing into it's own function for reuse.
    public function DrawHeader($header, $w) {
        // Colors, line width and bold font
        // Header
        $this->SetFillColor(233, 136, 64);
        $this->SetTextColor(255);
        $this->SetDrawColor(128, 0, 0);
        $this->SetLineWidth(0.3);
        $this->SetFont('', 'B');        
        $num_headers = count($header);
        for($i = 0; $i < $num_headers; ++$i) {
            $this->Cell($w[$i], 7, $header[$i], 1, 0, 'C', 1);
        }
        $this->Ln();
        // Color and font restoration
        $this->SetFillColor(224, 235, 255);
        $this->SetTextColor(0);
        $this->SetFont('');
    }

    // Colored table
    public function ColoredTable($header,$data) {
        $w = array(10, 40, 20, 20, 20, 20, 20);
        $this->DrawHeader($header, $w);

        // Data
        $fill = 0;
        foreach($data as $row) {
            //Get current number of pages.
            $num_pages = $this->getNumPages();
            $this->startTransaction();
            $this->Cell($w[0], 6, $row[0], 'LR', 0, 'C', $fill);
            $this->Cell($w[1], 6, $row[1], 'LR', 0, 'L', $fill);
            $this->Cell($w[2], 6, $row[2], 'LR', 0, 'C', $fill);
            $this->Cell($w[3], 6, $row[3], 'LR', 0, 'C', $fill);
            $this->Cell($w[4], 6, $row[4], 'LR', 0, 'C', $fill);
            $this->Cell($w[5], 6, $row[5], 'LR', 0, 'C', $fill);
            $this->Cell($w[6], 6, $row[6], 'LR', 0, 'C', $fill);
            $this->Ln();
            //If old number of pages is less than the new number of pages,
            //we hit an automatic page break, and need to rollback.
            if($num_pages < $this->getNumPages())
            {
                //Undo adding the row.
                $this->rollbackTransaction(true);
                //Adds a bottom line onto the current page. 
                //Note: May cause page break itself.
                $this->Cell(array_sum($w), 0, '', 'T');
                //Add a new page.
                $this->AddPage();
                //Draw the header.
                $this->DrawHeader($header, $w);
                //Re-do the row.
                $this->Cell($w[0], 6, $row[0], 'LR', 0, 'C', $fill);
                $this->Cell($w[1], 6, $row[1], 'LR', 0, 'L', $fill);
                $this->Cell($w[2], 6, $row[2], 'LR', 0, 'C', $fill);
                $this->Cell($w[3], 6, $row[3], 'LR', 0, 'C', $fill);
                $this->Cell($w[4], 6, $row[4], 'LR', 0, 'C', $fill);
                $this->Cell($w[5], 6, $row[5], 'LR', 0, 'C', $fill);
                $this->Cell($w[6], 6, $row[6], 'LR', 0, 'C', $fill);
                $this->Ln();
            }
            else
            {
                //Otherwise we are fine with this row, discard undo history.
                $this->commitTransaction();
            }
            $fill=!$fill;
        }
        $this->Cell(array_sum($w), 0, '', 'T');
    }
Modena answered 21/4, 2013 at 9:50 Comment(0)
D
54

Another method would be to simply use THEAD tag in html.

<table>
<thead>
    <tr><th>Heading</th></tr>
</thead>
<tbody>
    <tr><td>Many rows...</td></tr>
    <tr><td>of data</td></tr>
</tbody>
</table>

It appears TCPDF repeats the heading on every page.

Deaden answered 27/8, 2013 at 13:14 Comment(4)
how to determine the page is end and start second page then heading will add in new page.Finedrawn
This is a nice simple solution which worked well for me. One thing to add is that I needed to specify the column widths in both the THEAD and TBODY sections otherwise the columns go out of alignment. I did this with the style attribute, eg <td style="width: 100mm;">...</td>.Kristynkrock
Keep in mind, that this solution does not work for nested tables.Merlenemerlin
@SteveLockwood I am using this solution, I specified the width for every TD and TH but still starting from the second page the heading goes out of alignment. Any ideas?Filberto
M
13

Two methods come to my mind.

Method 1: Create your own custom header function (like in TCPDF example 3) that automatically adds the header cells to each page. In this scenario, you would move the header cell placement code into a Header method in your class and draw the headers to a fixed position on the page. Since the Header method is called automatically when a new page is added, your table headers would then be added as soon as the page is created. This is certainly faster and less intensive than method 2, but it can be a little tricky.

Method 2: Use TCPDF transactions to detect when a row is about to break the page, and then rollback. You would then AddPage yourself; draw the headers again; and continue with display. You can do this by getting the number of pages before you make the row, and comparing it to the number of pages after. An example of how you might do it this way as been provided:

    //Separated Header Drawing into it's own function for reuse.
    public function DrawHeader($header, $w) {
        // Colors, line width and bold font
        // Header
        $this->SetFillColor(233, 136, 64);
        $this->SetTextColor(255);
        $this->SetDrawColor(128, 0, 0);
        $this->SetLineWidth(0.3);
        $this->SetFont('', 'B');        
        $num_headers = count($header);
        for($i = 0; $i < $num_headers; ++$i) {
            $this->Cell($w[$i], 7, $header[$i], 1, 0, 'C', 1);
        }
        $this->Ln();
        // Color and font restoration
        $this->SetFillColor(224, 235, 255);
        $this->SetTextColor(0);
        $this->SetFont('');
    }

    // Colored table
    public function ColoredTable($header,$data) {
        $w = array(10, 40, 20, 20, 20, 20, 20);
        $this->DrawHeader($header, $w);

        // Data
        $fill = 0;
        foreach($data as $row) {
            //Get current number of pages.
            $num_pages = $this->getNumPages();
            $this->startTransaction();
            $this->Cell($w[0], 6, $row[0], 'LR', 0, 'C', $fill);
            $this->Cell($w[1], 6, $row[1], 'LR', 0, 'L', $fill);
            $this->Cell($w[2], 6, $row[2], 'LR', 0, 'C', $fill);
            $this->Cell($w[3], 6, $row[3], 'LR', 0, 'C', $fill);
            $this->Cell($w[4], 6, $row[4], 'LR', 0, 'C', $fill);
            $this->Cell($w[5], 6, $row[5], 'LR', 0, 'C', $fill);
            $this->Cell($w[6], 6, $row[6], 'LR', 0, 'C', $fill);
            $this->Ln();
            //If old number of pages is less than the new number of pages,
            //we hit an automatic page break, and need to rollback.
            if($num_pages < $this->getNumPages())
            {
                //Undo adding the row.
                $this->rollbackTransaction(true);
                //Adds a bottom line onto the current page. 
                //Note: May cause page break itself.
                $this->Cell(array_sum($w), 0, '', 'T');
                //Add a new page.
                $this->AddPage();
                //Draw the header.
                $this->DrawHeader($header, $w);
                //Re-do the row.
                $this->Cell($w[0], 6, $row[0], 'LR', 0, 'C', $fill);
                $this->Cell($w[1], 6, $row[1], 'LR', 0, 'L', $fill);
                $this->Cell($w[2], 6, $row[2], 'LR', 0, 'C', $fill);
                $this->Cell($w[3], 6, $row[3], 'LR', 0, 'C', $fill);
                $this->Cell($w[4], 6, $row[4], 'LR', 0, 'C', $fill);
                $this->Cell($w[5], 6, $row[5], 'LR', 0, 'C', $fill);
                $this->Cell($w[6], 6, $row[6], 'LR', 0, 'C', $fill);
                $this->Ln();
            }
            else
            {
                //Otherwise we are fine with this row, discard undo history.
                $this->commitTransaction();
            }
            $fill=!$fill;
        }
        $this->Cell(array_sum($w), 0, '', 'T');
    }
Modena answered 21/4, 2013 at 9:50 Comment(0)
U
2

This may be a bit late but I came up with a simple way to have headers on each page. Get the count of $data and use the array_slice function to populate a page worth of data rows. Output the table and then loop back to the next page. I use 54 rows per page with a font size of 9.

//Data loading
$data = $pdf->LoadData('text.txt');
$datacount = count($data);
$i = 0;
while ($i < $datacount) {
    $dataout = array_slice($data, $i, 54, false);
    $pdf->AddPage();
    // print colored table      
    $pdf->ColoredTable($header, $dataout);
    $i = $i + 54;
}

Underwriter answered 9/11, 2019 at 19:38 Comment(0)
A
2

I'm not allowed to add comments but I'd like to add some extra info to the solution of Specto. I think his solution is indeed the best/simplest way to achieve this, however it can happen that after a page_break the first row below the header gets partially deleted, or some other way the alignment/width/etc of cells is just broken. As of my findings this comes because of the table "breaks" in the middle of the row. To prevent this behaviour add nobr="true" to the rows.

<table>
<thead>
    <tr><th>Heading</th></tr>
</thead>
<tbody>
    <tr nobr="true"><td>Many rows...</td></tr>
    <tr nobr="true"><td>of data</td></tr>
</tbody>
</table>
Angelicangelica answered 22/6, 2020 at 17:13 Comment(0)
I
0

EPB's Method 2 worked for me but I modified it a little and just used $pdf->startTransaction(); instead of $this->startTransaction(); as my script was already formated in that way.

Thanks a lot!

Illlooking answered 9/5, 2013 at 16:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.