Templates

Informations

Author: David
License: FPDF

Description

This script adds templates to FPDF for building documents containing a large number of similar pages. Typically, when a PDF is built with many pages sharing the same layout while only text changes, it can prove useful to use a template which will be defined only once as a single object and will be included in each page requiring that layout.

A template is defined by an external file containing a subset of raw FPDF instructions. This approach brings several benefits:

Template rules

Anchor definition

To define a text anchor within a template, use SetTextProp() with the following arguments:
SetTextProp(string anchor_id, float x_pos, float y_pos, float width, float height, string font_family, string font style, float font_size)

To define a column anchor, use SetColumns() with the following arguments:
SetColumns(string anchor_id, float col00, float col01, float col02, ...,  float col18, float col19)
Caution: anchor IDs are cross-template which means that they should be unique for a given PDF. If two templates used in the same PDF have anchors with the same ID, the last one will take precedence. There is however a clear distinction between text and column anchors, which means that a text anchor and a column anchor can share the same ID.

The method to load a template is:
int LoadTemplate(string file_tpl [, boolean verbose])

file_tpl: file name containing the template.
verbose: boolean indicating if each processed instruction should be logged to stdout. Defaults to false.
If successful, this function returns a positive integer usable at a later stage by IncludeTemplate():
IncludeTemplate(int handle)

handle: handle returned by a previous call to LoadTemplate()
The method to output a text according to a set of properties defined in a template is:
array ApplyTextProperties(string anchor_id, string text])

anchor_id: anchor identifier specified in one of the templates previously loaded.
text: string containing the text to output. If empty, text properties are still applied (position, color, font).
If successful, the method returns an associative array with the following keys:
px  =>  X position (float)
py => Y position (float)
ix => width or delta_x (float)
iy => height or delta_y (float)
fr => text color - red component (int)
fg => text color - green component (int)
fb => text color - blue component (int)
fam => font family (string)
sty => font style (string)
siz => font size (float)
The method to retrieve an array of column widths associated with an anchor ID is:
array GetColumns(string anchor_id)

anchor_id: anchor identifier specified in one of the templates previously loaded.
If successful, this method returns an array containing the widths of up to 20 columns.

Example

Here's an example which builds a PDF containing 21 pages with data loaded from a CSV file.
The script invokes two distinct templates and demonstrates the usage of both types of anchors (text and column).
<?php 
require_once ('templates_fpdf.php');

// This sample program uses two distinct templates
$file_tpl1 = "template1.tpl";
$file_tpl2 = "template2.tpl";

// This sample program uses data fetched from a CSV file
$file_csv  = "data.csv";
$lines     = file ($file_csv);
$headers   = explode (";", $lines [0]);    // Headers for columns for the first page
$rows      = array_slice ($lines, 1);    // Data doesn't include the first row which contains headers 
$nb_rows   = count ($rows);

$pdf = new Templates_FPDF();
$pdf->AliasNbPages ("{nb}");            // For page numbering

// Template #1 is used for the part which builds one page per employee
$template1 = $pdf->LoadTemplate ($file_tpl1);
if ($template1 <= 0) {
    die ("  ** Error couldn't load template file '$file_tpl1'");
    }

// ====================================================
//   First page contains the table for all employees 
// ====================================================
    
$pdf->AddPage("L");

// Template #2 is used for the part which builds a table containing all employees
$template2 = $pdf->LoadTemplate ($file_tpl2);
if ($template2 <= 0) {
    die ("  ** Error couldn't load template file '$file_tpl2'");
    }
$pdf->IncludeTemplate ($template2);        
$pdf->ApplyTextProp ("FOOTRNB2", "1 / {nb}");   //  Add a footer with page number

// In the table of the first page, take into account only a subset of fields of CSV file; say fields #0,#2,#3,#5,#6,#7
$subset_csv = array (0, 2, 3, 5, 6, 7);
$nn = count ($subset_csv);

// Get collumns widths with an anchor ID
$pcol = $pdf->GetColls ("COLSWDTH", "");
// Get Text properties of headers
$ptxp = $pdf->ApplyTextProp ("ROW0COL0", "");

for ($ii = 0; $ii < $nn; $ii ++) {
    $data = $headers [$subset_csv [$ii]];
// Column interspace is 1
    $pdf->SetX ($pdf->GetX() + 1);
    $pdf->Cell ($pcol [$ii], $ptxp ['iy'], $data, 1, 0, "C", true);
    }

$pdf->SetFillColor (240, 240, 240);        // for "zebra" effect
// Get Text properties of data cell
$ptxp = $pdf->ApplyTextProp ("ROW1COL0", "");
$py = $ptxp ['py'];            // Initial Y position for data rows        
for ($jj = 0; $jj < $nb_rows; $jj ++) {
    $pdf->SetXY ($ptxp ['px'], $py);
    $fields = explode (";", $rows[$jj]);
    for ($ii = 0; $ii < $nn; $ii ++) {
        $data = trim ($fields [$subset_csv [$ii]]);
// Column interspace is 1
        $pdf->SetX ($pdf->GetX() + 1);
// Last fill boolean parameter switches from false to true to achieve a "zebra" effect
        $pdf->Cell ($pcol [$ii], $ptxp ['iy'], $data, "", 0, "L", $jj & 1);
        }
    $py += $ptxp ['iy'];        // for row interspace
    }
    
// ==================================================
//   Subsequent pages contain one page per employee 
// ==================================================
    
for ($ii = 0; $ii < $nb_rows; $ii ++) {
    $pdf->AddPage("P");
    $pdf->IncludeTemplate ($template1);
    $page_nb = $pdf->PageNo(); 
    $pdf->ApplyTextProp ("FOOTRNB1", "$page_nb / {nb}");   //  Add a footer with page number

    $fields = explode (";", $rows[$ii]);
    foreach ($fields as $kk => $field) {
        $anchor_id = "FIELD" . sprintf ("%03d", $kk);
        $pdf->ApplyTextProp ($anchor_id, trim ($field));
        }
    }

$nb_pages = $pdf->PageNo();
$file_pdf = "ex.pdf";    
$pdf->Output("F", $file_pdf);
print ("  >> File '$file_pdf' generated:  " . "$nb_pages pages  -  " . filesize($file_pdf) . " bytes\n");
?>
View the result here.

Download

ZIP | TGZ