Pages

Tuesday, March 23, 2021

Create Nice-Looking PDFs with PHP and FPDF

 The PDF format can be a handy way to distribute documents to your visitors. A PDF document is self-contained, looks the same on any PDF reader, and is easy to print. PDFs are often used for reports, brochures, manuals, invoices, product data sheets, and lots more.

Often it’s useful to be able to create PDF documents dynamically from within a PHP script. For example, you can produce a custom PDF report based on a user’s preferences and include up-to-the-minute data.

In this tutorial I’ll walk you through the process of creating a nice-looking, 2-page PDF document using PHP. You’ll use the freely-available FPDF library to handle the nitty-gritty of PDF creation.

Here’s what your PDF will look like (click to view the finished PDF):


Installing FPDF

To use FPDF, you first need to install the FPDF files on your website. To do this, download the FPDF archive file and extract it to a folder within your website. Call the folder fpdf.

Starting the PHP script

Now that you’ve installed FPDF, you can start writing your PHP script to produce the PDF report. Create a file called report.php in the same place that you saved your fpdf folder, and open the file in a text editor.

The first thing to do is include the FPDF library so that you can use it. The library is called fpdf.php, and it’s inside the fpdf folder that you extracted earlier:


<?php

require_once( "fpdf/fpdf.php" );

Now add some variables to configure the report:


// Begin configuration

$textColour = array( 0, 0, 0 );
$headerColour = array( 100, 100, 100 );
$tableHeaderTopTextColour = array( 255, 255, 255 );
$tableHeaderTopFillColour = array( 125, 152, 179 );
$tableHeaderTopProductTextColour = array( 0, 0, 0 );
$tableHeaderTopProductFillColour = array( 143, 173, 204 );
$tableHeaderLeftTextColour = array( 99, 42, 57 );
$tableHeaderLeftFillColour = array( 184, 207, 229 );
$tableBorderColour = array( 50, 50, 50 );
$tableRowFillColour = array( 213, 170, 170 );
$reportName = "2009 Widget Sales Report";
$reportNameYPos = 160;
$logoFile = "widget-company-logo.png";
$logoXPos = 50;
$logoYPos = 108;
$logoWidth = 110;
$columnLabels = array( "Q1", "Q2", "Q3", "Q4" );
$rowLabels = array( "SupaWidget", "WonderWidget", "MegaWidget", "HyperWidget" );
$chartXPos = 20;
$chartYPos = 250;
$chartWidth = 160;
$chartHeight = 80;
$chartXLabel = "Product";
$chartYLabel = "2009 Sales";
$chartYStep = 20000;

$chartColours = array(
                  array( 255, 100, 100 ),
                  array( 100, 255, 100 ),
                  array( 100, 100, 255 ),
                  array( 255, 255, 100 ),
                );

$data = array(
          array( 9940, 10100, 9490, 11730 ),
          array( 19310, 21140, 20560, 22590 ),
          array( 25110, 26260, 25210, 28370 ),
          array( 27650, 24550, 30040, 31980 ),
        );

// End configuration

These variables make it easy to tweak your report by keeping all the key configuration data at the top of the file. The variables include:

  • Various colours used in the report. Each colour is specified as a 3-element array containing red, green and blue values (in the range 0-255).
  • The report title (“2009 Widget Sales Report”) and position.
  • The URL and dimensions of the company logo image. You’ll include this image in the title page of the report.
  • The row and column labels for the report data. You’ll use these when displaying the table and chart in the report.
  • Configuration settings for the chart. These include the chart position, dimensions, axis labels, and the step value to use for the Y-axis scale.
  • The colours to use for the chart bars. As with the other report colours, these are specified as 3-element arrays. There are 4 colours: 1 for each bar in the chart.
  • The report data. This is a 2-dimensional array containing 4 rows of quarterly sales figures, 1 row per product.

Creating the title page

Now that you’ve set up the report configuration, you’re ready to start building the PDF. First, you’ll create the title page for the report. This consists of the company logo and the report name, centred in the page.

Creating the FPDF object

The first thing you need to do is create a new FPDF object to hold the PDF data. The FPDF constructor accepts 3 optional arguments, as follows:

  • The page orientation. Use 'P' for portrait, or 'L' for landscape. The default is 'P'.
  • The units to use for the page measurements. Use 'pt', 'mm', 'cm', or 'in'. The default is 'mm'.
  • The page format. Possible values include 'A3', 'A4', 'A5', 'Letter', and 'Legal'. Or you can specify a custom width and height with a 2-element array. The default value is 'A4'.

For this example, use a portrait orientation, millimetres for units, and A4 format:


/**
  Create the title page
**/

$pdf = new FPDF( 'P', 'mm', 'A4' );

Setting the text colour

Now set the colour to use for text in the page. You do this by calling the FPDF SetTextColor() method, passing in the red, green and blue values of the colour to use (each value should be in the range 0-255). Use the colour values in the $textColour array that you created in the configuration section earlier:


$pdf->SetTextColor( $textColour[0], $textColour[1], $textColour[2] );

Creating a page

Now you’re ready to create a new blank page in the PDF by calling FPDF’s
AddPage()
method:


$pdf->AddPage();

Adding the logo image

FPDF makes it really easy to insert images in the page. Just call the Image() method, passing in the following arguments:

  • The path of the image file. This can be an absolute path, or relative to the PHP script. You can also use a URL.
  • The X and Y position of the top left corner of the image in the PDF. If you omit these then the current position is used.
  • The width and height of the image in the PDF. If you omit both values then the original image dimensions are used (at 72 DPI). If you omit 1 value then the other value is calculated automatically.
  • The image type. Allowed values include 'JPG', ‘JPEG', 'PNG' and 'GIF' (upper- or lower-case). If you omit this value then FPDF guesses the image format from the filename extension.
  • A URL to link the image to. This is optional — if you supply a URL then the image becomes a clickable link.

All measurements, such as X and Y positions, widths and heights, use the units you specified when you created the PDF (mm in this case).

You can create your own logo image (make sure it’s 300 DPI) or download my example image. Save your logo image in the same folder as your PHP script, then insert the image in the PDF as follows:


// Logo
$pdf->Image( $logoFile, $logoXPos, $logoYPos, $logoWidth );

Setting the font

FPDF lets you choose the font face, style and size to use for text in the PDF. To do this, you call the SetFont() method, which takes the following arguments:

  • The font family. You can use any of the following standard family names: 'Courier', 'Helvetica', 'Arial', 'Times', 'Symbol', or 'ZapfDingbats'.
  • The font style. Options include: '' (regular), 'B' (bold), 'I' (italic), and 'U' (underline). You can combine these — for example, 'BU' for bold, underlined text.
  • The font size. You specify this in points (it defaults to 12 points).

For the report name on the title page, use an Arial Bold 24-point font:


// Report Name
$pdf->SetFont( 'Arial', 'B', 24 );

As well as using the standard fonts, you can import any TrueType or Type 1 font using the AddFont() method. See the manual on the FPDF website for details.

Adding some text

You’re now ready to add the report name. FPDF objects have a concept of “the current position”, which is where the next piece of text or other element will be inserted. Since you want the report name to appear just after halfway down the page, you first need to move the current position down to this point, which is 160mm from the top of the page (this is stored in the $reportNameYPos configuration variable). To do this, use FPDF’s Ln() method, which adds a line break with an optional height value:


$pdf->Ln( $reportNameYPos );

If you don’t specify a height for the line break then the height of the last printed cell is used.

Now add the report name. There are a few different ways that you can add text using FPDF. In this case, you’ll use the Cell() method, which, amongst other things, lets you easily centre text.

Cell() takes the following arguments (all of them optional):

  • The cell width and height. If you omit the width then the cell stretches to the right margin. If you omit the height then it defaults to zero.
  • The string of text to print. Defaults to ''.
  • Whether to draw a border around the cell. This can be either a number (0=no border, 1=border), or a string containing 1 or more of the following: 'L' (left), 'T' (top), 'R' (right), and 'B' (bottom). Default: 0.
  • Where to place the current position after drawing the cell. Values can be 0 (to the right), 1 (to the start of the next line), or 2 (below). Default: 0.
  • The text alignment. Possible values are 'L' (left align), 'C' (centre), or 'R' (right align). Default: 'L'.
  • Whether the cell background should be filled with colour. true = filled, false = transparent. Default: false.
  • A URL to link to. If specified, turns the text cell into a link.

Now, use Cell() to insert the report name and centre it, as follows:


$pdf->Cell( 0, 15, $reportName, 0, 0, 'C' );

Creating a page header and intro text

That’s the title page done. Now you’ll create the page containing some header text, a heading, and some intro text, followed by a table and chart of sales data.

First the page header. Add a new page, then output the page header, which consists of the report name centred at the top of the page using an Arial Regular 17-point font. Use the $headerColour configuration variable to set the text colour:


$pdf->AddPage();
$pdf->SetTextColor( $headerColour[0], $headerColour[1], $headerColour[2] );
$pdf->SetFont( 'Arial', '', 17 );
$pdf->Cell( 0, 15, $reportName, 0, 0, 'C' );

Now for the intro text. First print a heading using the regular text colour and an Arial 20-point font. Since you don’t need this text to be centred, you can use the simpler Write() method, which takes the line height, the text to write, and an optional link URL:


$pdf->SetTextColor( $textColour[0], $textColour[1], $textColour[2] );
$pdf->SetFont( 'Arial', '', 20 );
$pdf->Write( 19, "2009 Was A Good Year" );

Now you can output the intro text itself in 12-point Arial. This consists of a 16mm line break, followed by the first paragraph, a 12mm line break, and the final paragraph. Give each line a line height of 6mm:


$pdf->Ln( 16 );
$pdf->SetFont( 'Arial', '', 12 );
$pdf->Write( 6, "Despite the economic downturn, WidgetCo had a strong year. Sales of the HyperWidget in particular exceeded expectations. The fourth quarter was generally the best performing; this was most likely due to our increased ad spend in Q3." );
$pdf->Ln( 12 );
$pdf->Write( 6, "2010 is expected to see increased sales growth as we expand into other countries." );

The Write() method automatically wraps text when it reaches the right side of the page.

Adding a table of data

Next you’ll add a table of sales data below the intro text. First, set the border colour for the table. The SetDrawColor() method sets the colour to use for borders and other lines, so you can use this to set the table cell borders. Then move down 15mm to create a space between the intro text and the table:


$pdf->SetDrawColor( $tableBorderColour[0], $tableBorderColour[1], $tableBorderColour[2] );
$pdf->Ln( 15 );

Creating the table header row

The table header row consists of the “PRODUCT”, “Q1, “Q2”, “Q3”, and “Q4” cells. The “PRODUCT” cell uses different text and background colours to the other header cells.

You already know to call the SetTextColor() method to set the text colour to use. To set the background colour to use, you call SetFillColor(), which takes the same RGB arguments as SetTextColor().

To create table cells you use — you guessed it — the Cell() method, specifying the cell width, height, contents, and alignment. You’ll also pass 1 as the 4th argument to set a border, and true as the 7th argument to fill the cell with a background colour.

Here, then, is the code to create the table header row. First you set a bold font, then create the left-aligned “PRODUCT” cell with appropriate text and fill colours. Finally, you set colours for the remaining 4 header cells, then loop through the $columnLabels array to display the cells using centred text:


// Create the table header row
$pdf->SetFont( 'Arial', 'B', 15 );

// "PRODUCT" cell
$pdf->SetTextColor( $tableHeaderTopProductTextColour[0], $tableHeaderTopProductTextColour[1], $tableHeaderTopProductText
Colour[2] );
$pdf->SetFillColor( $tableHeaderTopProductFillColour[0], $tableHeaderTopProductFillColour[1], $tableHeaderTopProductFill
Colour[2] );
$pdf->Cell( 46, 12, " PRODUCT", 1, 0, 'L', true );

// Remaining header cells
$pdf->SetTextColor( $tableHeaderTopTextColour[0], $tableHeaderTopTextColour[1], $tableHeaderTopTextColour[2] );
$pdf->SetFillColor( $tableHeaderTopFillColour[0], $tableHeaderTopFillColour[1], $tableHeaderTopFillColour[2] );

for ( $i=0; $i<count($columnLabels); $i++ ) {
  $pdf->Cell( 36, 12, $columnLabels[$i], 1, 0, 'C', true );
}

$pdf->Ln( 12 );

The space character before the word “PRODUCT” in the code helps to pad the word within the table cell so that it isn’t hard up against the left edge of the cell. The same trick is used later on with the product names in the left hand column. (Unfortunately there’s currently no way to control cell padding with FPDF without extending the class.)

Creating the data rows

The rest of the table consists of 4 rows of sales figures — 1 row for each product — over the 4 quarters. First, set a couple of variables:


// Create the table data rows

$fill = false;
$row = 0;

These variables work as follows:

$fill
Whether a cell should be filled or not. You’ll toggle this value every time you’ve drawn a row to create a striped row effect.
$row
The current row number. This lets you display the appropriate row label for each row as you move through the table.

Now you can loop through the $data array using a foreach loop, printing a row at a time. For each row you create the left header cell containing the product name, and the 4 data cells containing the sales data. Set appropriate text and background colours for each cell as you go.

To display the data cells, use a for loop to move through the 4-element array containing the data, calling the PHP number_format() function to print the sales figure with thousands separators.

After displaying a row, you increment the $row variable, toggle the $fill variable, and use Ln() to move down to the start of the next line, ready to output the next row.

Here’s the code for the whole loop:


foreach ( $data as $dataRow ) {

  // Create the left header cell
  $pdf->SetFont( 'Arial', 'B', 15 );
  $pdf->SetTextColor( $tableHeaderLeftTextColour[0], $tableHeaderLeftTextColour[1], $tableHeaderLeftTextColour[2] );
  $pdf->SetFillColor( $tableHeaderLeftFillColour[0], $tableHeaderLeftFillColour[1], $tableHeaderLeftFillColour[2] );
  $pdf->Cell( 46, 12, " " . $rowLabels[$row], 1, 0, 'L', $fill );

  // Create the data cells
  $pdf->SetTextColor( $textColour[0], $textColour[1], $textColour[2] );
  $pdf->SetFillColor( $tableRowFillColour[0], $tableRowFillColour[1], $tableRowFillColour[2] );
  $pdf->SetFont( 'Arial', '', 15 );

  for ( $i=0; $i<count($columnLabels); $i++ ) {
    $pdf->Cell( 36, 12, ( '$' . number_format( $dataRow[$i] ) ), 1, 0, 'C', $fill );
  }

  $row++;
  $fill = !$fill;
  $pdf->Ln( 12 );
}

Creating a bar chart

The last element of the page is a bar chart showing the total sales figures for the 4 products over the whole year.

Calculating scales and bar width

The first thing to do is compute the scales for the X and Y axes. For the X scale this is simply the number of products to display divided by the desired chart width (subtracting some millimetres to allow for space to the left of the bars):


/***
  Create the chart
***/

// Compute the X scale
$xScale = count($rowLabels) / ( $chartWidth - 40 );

To compute the Y scale, you need to find the total sales figure for each product, then determine the highest sales figure across all the products. You can then divide this by the desired chart height to get the Y scale:


// Compute the Y scale

$maxTotal = 0;

foreach ( $data as $dataRow ) {
  $totalSales = 0;
  foreach ( $dataRow as $dataCell ) $totalSales += $dataCell;
  $maxTotal = ( $totalSales > $maxTotal ) ? $totalSales : $maxTotal;
}

$yScale = $maxTotal / $chartHeight;

Now that you know the X scale, you can work out the width (in mm) of each bar in the chart. This is the inverse of the X scale value, reduced by a factor of 1.5 to allow some space between each bar:


// Compute the bar width
$barWidth = ( 1 / $xScale ) / 1.5;

Adding the axis lines and labels

So far, so good. Now you can add the X and Y axis lines, data labels, and axis labels. Use Arial 10-point for the data labels.

To create lines in FDPF, you use the Line() method, which accepts 4 arguments: the X and Y co-ordinates of the start of the line, and the X and Y co-ordinates of the end of the line.

For the X axis, draw a horizontal line along the bottom of the chart, allowing 30mm for the Y-axis labels on the left. Then loop through each product name in the $rowLabels array, printing the product name as a text cell at the appropriate point:


// Add the axes:

$pdf->SetFont( 'Arial', '', 10 );

// X axis
$pdf->Line( $chartXPos + 30, $chartYPos, $chartXPos + $chartWidth, $chartYPos );

for ( $i=0; $i < count( $rowLabels ); $i++ ) {
  $pdf->SetXY( $chartXPos + 40 +  $i / $xScale, $chartYPos );
  $pdf->Cell( $barWidth, 10, $rowLabels[$i], 0, 0, 'C' );
}

The SetXY() method lets you set the current position to a specific location on the page.

For the Y axis, draw a vertical line up the left side of the chart, again allowing 30mm for the Y-axis labels. Extend the line 8mm above the desired chart height to make room for the axis label later on. Then loop from zero up to the highest bar value, $maxTotal, that you calculated earlier. Jump in steps of $chartYStep (20,000) dollars. At each step, display the current value (right-aligned) and a short tick mark:


// Y axis
$pdf->Line( $chartXPos + 30, $chartYPos, $chartXPos + 30, $chartYPos - $chartHeight - 8 );

for ( $i=0; $i <= $maxTotal; $i += $chartYStep ) {
  $pdf->SetXY( $chartXPos + 7, $chartYPos - 5 - $i / $yScale );
  $pdf->Cell( 20, 10, '$' . number_format( $i ), 0, 0, 'R' );
  $pdf->Line( $chartXPos + 28, $chartYPos - $i / $yScale, $chartXPos + 30, $chartYPos - $i / $yScale );
}

Now you can add the axis labels. Use Arial Bold 12-point. Place the X-axis label below the data labels, and the Y-axis label at the top of the Y axis:


// Add the axis labels
$pdf->SetFont( 'Arial', 'B', 12 );
$pdf->SetXY( $chartWidth / 2 + 20, $chartYPos + 8 );
$pdf->Cell( 30, 10, $chartXLabel, 0, 0, 'C' );
$pdf->SetXY( $chartXPos + 7, $chartYPos - $chartHeight - 12 );
$pdf->Cell( 20, 10, $chartYLabel, 0, 0, 'R' );

Drawing the data bars

The last stage of creating the chart is to draw the bars themselves. To draw a bar you can use FPDF’s Rect() method, which draws a rectangle using the following arguments:

  • The X and Y co-ordinates of the upper left corner of the rectangle.
  • The width and height of the rectangle.
  • The rectangle style. This can be 'D' or '' (draw a border), 'F' (fill with the current fill colour), or 'DF' / 'FD' (draw and fill).

Now draw the bars. First, Set a variable, $xPos, to track the current bar X position; set it 40mm to the right of the chart’s start position to allow for the Y-axis labels and a gap at the start of the bars. Then create a variable, $bar, to hold the current bar number; you’ll use this to work out which fill colour to use for each bar:


// Create the bars
$xPos = $chartXPos + 40;
$bar = 0;

Now loop through the $data array, totalling up the value in each row and drawing a bar from the X axis up to that value, scaled using $yScale. Colour each bar differently by using the $bar counter and the colour values in the $chartColours array. After you’ve drawn each bar, move the X position along to the start of the next bar, increment the $bar counter, and continue the loop:


foreach ( $data as $dataRow ) {

  // Total up the sales figures for this product
  $totalSales = 0;
  foreach ( $dataRow as $dataCell ) $totalSales += $dataCell;

  // Create the bar
  $colourIndex = $bar % count( $chartColours );
  $pdf->SetFillColor( $chartColours[$colourIndex][0], $chartColours[$colourIndex][1], $chartColours[$colourIndex][2] );
  $pdf->Rect( $xPos, $chartYPos - ( $totalSales / $yScale ), $barWidth, $totalSales / $yScale, 'DF' );
  $xPos += ( 1 / $xScale );
  $bar++;
}

The above code uses the PHP modulus (%) operator to repeat the bar colours if the number of bars happens to be greater than the number of elements in the $chartColours array.

Sending the PDF to the browser

Your PDF is finished! The only thing left to do is send the PDF to the browser so that the user can view or download it.

To do this, you call FPDF’s Output() method to send the PDF data. This accepts 2 arguments: the suggested filename for the PDF, and a destination flag. This flag can have any of the following values:

I
Displays the PDF inline if supported by the browser, otherwise it’s downloaded.
D
Forces the PDF to be downloaded.
F
Saves the file to a folder on the server.
S
Returns the PDF data as a string.

For this example, use the I option to display the PDF inline if possible:


/***
  Serve the PDF
***/

$pdf->Output( "report.pdf", "I" );

?>

Output() automatically sends an HTTP "Content-type: application/pdf" header, which tells the browser to expect a PDF document.

You’re now ready to test your script. Open your browser and visit the script’s URL — for example, www.example.com/report.php. You should see the PDF appear in your browser window. Alternatively you might see a dialog appear that lets you save the PDF to your hard drive. You can then open up the PDF in your PDF viewer, such as Acrobat Reader or Preview.

That’s it! You’ve now created a PDF document on the fly using nothing but PHP and FPDF. Good work!

The complete script

Here’s the complete PHP script for you to copy, paste, and play with:


<?php

/*
  An Example PDF Report Using FPDF
  by Matt Doyle

  From "Create Nice-Looking PDFs with PHP and FPDF"
  http://www.elated.com/articles/create-nice-looking-pdfs-php-fpdf/
*/

require_once( "fpdf/fpdf.php" );

// Begin configuration

$textColour = array( 0, 0, 0 );
$headerColour = array( 100, 100, 100 );
$tableHeaderTopTextColour = array( 255, 255, 255 );
$tableHeaderTopFillColour = array( 125, 152, 179 );
$tableHeaderTopProductTextColour = array( 0, 0, 0 );
$tableHeaderTopProductFillColour = array( 143, 173, 204 );
$tableHeaderLeftTextColour = array( 99, 42, 57 );
$tableHeaderLeftFillColour = array( 184, 207, 229 );
$tableBorderColour = array( 50, 50, 50 );
$tableRowFillColour = array( 213, 170, 170 );
$reportName = "2009 Widget Sales Report";
$reportNameYPos = 160;
$logoFile = "widget-company-logo.png";
$logoXPos = 50;
$logoYPos = 108;
$logoWidth = 110;
$columnLabels = array( "Q1", "Q2", "Q3", "Q4" );
$rowLabels = array( "SupaWidget", "WonderWidget", "MegaWidget", "HyperWidget" );
$chartXPos = 20;
$chartYPos = 250;
$chartWidth = 160;
$chartHeight = 80;
$chartXLabel = "Product";
$chartYLabel = "2009 Sales";
$chartYStep = 20000;

$chartColours = array(
                  array( 255, 100, 100 ),
                  array( 100, 255, 100 ),
                  array( 100, 100, 255 ),
                  array( 255, 255, 100 ),
                );

$data = array(
          array( 9940, 10100, 9490, 11730 ),
          array( 19310, 21140, 20560, 22590 ),
          array( 25110, 26260, 25210, 28370 ),
          array( 27650, 24550, 30040, 31980 ),
        );

// End configuration


/**
  Create the title page
**/

$pdf = new FPDF( 'P', 'mm', 'A4' );
$pdf->SetTextColor( $textColour[0], $textColour[1], $textColour[2] );
$pdf->AddPage();

// Logo
$pdf->Image( $logoFile, $logoXPos, $logoYPos, $logoWidth );

// Report Name
$pdf->SetFont( 'Arial', 'B', 24 );
$pdf->Ln( $reportNameYPos );
$pdf->Cell( 0, 15, $reportName, 0, 0, 'C' );


/**
  Create the page header, main heading, and intro text
**/

$pdf->AddPage();
$pdf->SetTextColor( $headerColour[0], $headerColour[1], $headerColour[2] );
$pdf->SetFont( 'Arial', '', 17 );
$pdf->Cell( 0, 15, $reportName, 0, 0, 'C' );
$pdf->SetTextColor( $textColour[0], $textColour[1], $textColour[2] );
$pdf->SetFont( 'Arial', '', 20 );
$pdf->Write( 19, "2009 Was A Good Year" );
$pdf->Ln( 16 );
$pdf->SetFont( 'Arial', '', 12 );
$pdf->Write( 6, "Despite the economic downturn, WidgetCo had a strong year. Sales of the HyperWidget in particular exceeded expectations. The fourth quarter was generally the best performing; this was most likely due to our increased ad spend in Q3." );
$pdf->Ln( 12 );
$pdf->Write( 6, "2010 is expected to see increased sales growth as we expand into other countries." );


/**
  Create the table
**/

$pdf->SetDrawColor( $tableBorderColour[0], $tableBorderColour[1], $tableBorderColour[2] );
$pdf->Ln( 15 );

// Create the table header row
$pdf->SetFont( 'Arial', 'B', 15 );

// "PRODUCT" cell
$pdf->SetTextColor( $tableHeaderTopProductTextColour[0], $tableHeaderTopProductTextColour[1], $tableHeaderTopProductTextColour[2] );
$pdf->SetFillColor( $tableHeaderTopProductFillColour[0], $tableHeaderTopProductFillColour[1], $tableHeaderTopProductFillColour[2] );
$pdf->Cell( 46, 12, " PRODUCT", 1, 0, 'L', true );

// Remaining header cells
$pdf->SetTextColor( $tableHeaderTopTextColour[0], $tableHeaderTopTextColour[1], $tableHeaderTopTextColour[2] );
$pdf->SetFillColor( $tableHeaderTopFillColour[0], $tableHeaderTopFillColour[1], $tableHeaderTopFillColour[2] );

for ( $i=0; $i<count($columnLabels); $i++ ) {
  $pdf->Cell( 36, 12, $columnLabels[$i], 1, 0, 'C', true );
}

$pdf->Ln( 12 );

// Create the table data rows

$fill = false;
$row = 0;

foreach ( $data as $dataRow ) {

  // Create the left header cell
  $pdf->SetFont( 'Arial', 'B', 15 );
  $pdf->SetTextColor( $tableHeaderLeftTextColour[0], $tableHeaderLeftTextColour[1], $tableHeaderLeftTextColour[2] );
  $pdf->SetFillColor( $tableHeaderLeftFillColour[0], $tableHeaderLeftFillColour[1], $tableHeaderLeftFillColour[2] );
  $pdf->Cell( 46, 12, " " . $rowLabels[$row], 1, 0, 'L', $fill );

  // Create the data cells
  $pdf->SetTextColor( $textColour[0], $textColour[1], $textColour[2] );
  $pdf->SetFillColor( $tableRowFillColour[0], $tableRowFillColour[1], $tableRowFillColour[2] );
  $pdf->SetFont( 'Arial', '', 15 );

  for ( $i=0; $i<count($columnLabels); $i++ ) {
    $pdf->Cell( 36, 12, ( '$' . number_format( $dataRow[$i] ) ), 1, 0, 'C', $fill );
  }

  $row++;
  $fill = !$fill;
  $pdf->Ln( 12 );
}


/***
  Create the chart
***/

// Compute the X scale
$xScale = count($rowLabels) / ( $chartWidth - 40 );

// Compute the Y scale

$maxTotal = 0;

foreach ( $data as $dataRow ) {
  $totalSales = 0;
  foreach ( $dataRow as $dataCell ) $totalSales += $dataCell;
  $maxTotal = ( $totalSales > $maxTotal ) ? $totalSales : $maxTotal;
}

$yScale = $maxTotal / $chartHeight;

// Compute the bar width
$barWidth = ( 1 / $xScale ) / 1.5;

// Add the axes:

$pdf->SetFont( 'Arial', '', 10 );

// X axis
$pdf->Line( $chartXPos + 30, $chartYPos, $chartXPos + $chartWidth, $chartYPos );

for ( $i=0; $i < count( $rowLabels ); $i++ ) {
  $pdf->SetXY( $chartXPos + 40 +  $i / $xScale, $chartYPos );
  $pdf->Cell( $barWidth, 10, $rowLabels[$i], 0, 0, 'C' );
}

// Y axis
$pdf->Line( $chartXPos + 30, $chartYPos, $chartXPos + 30, $chartYPos - $chartHeight - 8 );

for ( $i=0; $i <= $maxTotal; $i += $chartYStep ) {
  $pdf->SetXY( $chartXPos + 7, $chartYPos - 5 - $i / $yScale );
  $pdf->Cell( 20, 10, '$' . number_format( $i ), 0, 0, 'R' );
  $pdf->Line( $chartXPos + 28, $chartYPos - $i / $yScale, $chartXPos + 30, $chartYPos - $i / $yScale );
}

// Add the axis labels
$pdf->SetFont( 'Arial', 'B', 12 );
$pdf->SetXY( $chartWidth / 2 + 20, $chartYPos + 8 );
$pdf->Cell( 30, 10, $chartXLabel, 0, 0, 'C' );
$pdf->SetXY( $chartXPos + 7, $chartYPos - $chartHeight - 12 );
$pdf->Cell( 20, 10, $chartYLabel, 0, 0, 'R' );

// Create the bars
$xPos = $chartXPos + 40;
$bar = 0;

foreach ( $data as $dataRow ) {

  // Total up the sales figures for this product
  $totalSales = 0;
  foreach ( $dataRow as $dataCell ) $totalSales += $dataCell;

  // Create the bar
  $colourIndex = $bar % count( $chartColours );
  $pdf->SetFillColor( $chartColours[$colourIndex][0], $chartColours[$colourIndex][1], $chartColours[$colourIndex][2] );
  $pdf->Rect( $xPos, $chartYPos - ( $totalSales / $yScale ), $barWidth, $totalSales / $yScale, 'DF' );
  $xPos += ( 1 / $xScale );
  $bar++;
}


/***
  Serve the PDF
***/

$pdf->Output( "report.pdf", "I" );

?>


I

Generating PDF files with PHP and FPDF

 This tutorial provides an overview of the FPDF functionality and two examples using the PHP object-oriented approach to get you started with building your own PDFs.

PHP allows you to generate PDF files dynamically, which can be useful for a variety of tasks. FPDF is a free PHP class containing a number of functions that let you create and manipulate PDFs.

PDFlib

The PHP API contains a number of functions for handling PDF files designed to be used with the PDFlib. Although extensive, this library is not free for commercial use. A free version called PDFlib Lite is available for personal use, but is limited in functionality. To use the full PDFlib library you must purchase a rather expensive license.

Why FPDF?

An alternative way of generating PDF files with PHP is using FPDF, a free PHP class containing a number of functions for creating and manipulating PDFs. The key word here is free. You are free to download and use this class or customise it to fit your needs. In addition to being free, it's also simpler to use than PDFlib. The PDFlib needs to be installed as an extension in your PHP package, whereas FPDF can just be included in your PHP script and it's ready to use.

Creating PDF files

To get started, you will need to download the FPDF class from the FPDF Web site and include it in your PHP script like this:

require('fpdf.php');

Below is an example of how you can generate a simple PDF using FPDF.

We begin by creating a new FPDF object with:

$pdf= new FPDF();

The FPDF constructor can take the following parameters:

|>String orientation (P or L) -- portrait or landscape
|>String unit (pt,mm,cm and in) -- measure unit
|>Mixed format (A3, A4, A5, Letter and Legal) -- format of pages

Next, we are going to set some document properties:

$pdf->SetAuthor('Lana Kovacevic');
$pdf->SetTitle('FPDF tutorial');

Because we want to use the same font throughout the whole document, we can set it before we create a page.

$pdf->SetFont('Helvetica','B',20);
$pdf->SetTextColor(50,60,100);

The SetFont function takes three parameters; the font family, style and size. We are using Helvetica, Bold and 20 points, which will be applied to the title of our document. You can either use one of the regular font families or set up a different one using the AddFont () function.

With SetTextColor () we are also setting the font colour for the entire document. The colours can be represented as RGB or grey scale. Here we are using RGB values.

Now that that's done, let's set up a page for our PDF document.

$pdf->AddPage('P');
$pdf->SetDisplayMode(real,'default');

You can pass the AddPage () a parameter of "P" or "L" to specify the page orientation. I've used "P" for portrait. The SetDisplayMode function determines how the page will be displayed. You can pass it zoom and layout parameters. Here we're using 100 percent zoom and the viewer's default layout.

Now, that we've set up a page, let's insert an image to make it look nicer and make it a link while we're at it. We'll display the FPDF logo by calling the Image function and passing it the following parameters -- name of the file, the dimensions and the URL.

$pdf->Image('logo.png',10,20,33,0,' ','http://www.fpdf.org/');

You could have also inserted the link with:

$pdf->Link(10, 20, 33,33, 'http://www.fpdf.org/');

Now let's make a title for our document with a border around it.

$pdf->SetXY(50,20);
$pdf->SetDrawColor(50,60,100);
$pdf->Cell(100,10,'FPDF Tutorial',1,0,'C',0);

The SetXY function sets the position of x and y coordinates, where we want the title to appear. SetDrawColor will set the colour of the border, using RGB values. After that's done, we call the Cell function to print out a cell rectangle along with the text of our title. We are passing the function the following parameters; width, height, text, border, ln, align and fill. The border is either 0 for no border or 1 for frame. For ln we are using the default value 0, "C" to centre align the text inside it and 0 for fill. Had we used 1 for fill the rectangle would have been coloured in. With a value of 0 we are making it transparent.

Now we want to write the main text to the PDF, that is display a little message.

$pdf->SetXY(10,50);
$pdf->SetFontSize(10);
$pdf->Write(5,'Congratulations! You have generated a PDF. ');

Again we are setting the x and y positions of the text, but this time we are reducing the font size with the SetFontSize function. The write function will print the text to a PDF. The parameter 5 will set the line height. This is only relevant however, if there are multiple lines of text.

Finally we want to send the output to a given destination, using the Output function.

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

Here we are passing the function the name of the file and the destination, in this case "I". The "I" parameter will send the output to the browser.

Putting it all together:

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

//create a FPDF object
$pdf=new FPDF();

//set document properties
$pdf->SetAuthor('Lana Kovacevic');
$pdf->SetTitle('FPDF tutorial');

//set font for the entire document
$pdf->SetFont('Helvetica','B',20);
$pdf->SetTextColor(50,60,100);

//set up a page
$pdf->AddPage('P');
$pdf->SetDisplayMode(real,'default');

//insert an image and make it a link
$pdf->Image('logo.png',10,20,33,0,' ','http://www.fpdf.org/');

//display the title with a border around it
$pdf->SetXY(50,20);
$pdf->SetDrawColor(50,60,100);
$pdf->Cell(100,10,'FPDF Tutorial',1,0,'C',0);

//Set x and y position for the main text, reduce font size and write content
$pdf->SetXY (10,50);
$pdf->SetFontSize(10);
$pdf->Write(5,'Congratulations! You have generated a PDF.');

//Output the document
$pdf->Output('example1.pdf','I');
?>

Now that you've learnt how to generate a simple PDF, let's see what else we can do with FPDF. The example code below demonstrates how to make a header and a footer for your document.


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

class PDF extends FPDF
{
  function Header()
    {
      $this->Image('logo.png',10,8,33);
      $this->SetFont('Helvetica','B',15);
      $this->SetXY(50, 10);
      $this->Cell(0,10,'This is a header',1,0,'C');
     }

  function Footer()
    {
      $this->SetXY(100,-15);
      $this->SetFont('Helvetica','I',10);
      $this->Write (5, 'This is a footer');
    }
}

$pdf=new PDF();
$pdf->AddPage();
$pdf->Output('example2.pdf','D');
?>


As you can see we are creating a child class of FPDF using inheritance and setting up the behaviour for both the Header and Footer functions. We then create a new object of this PDF class and add a page to our document. The AddPage () will automatically call the Header and Footer. Finally, we output it to a file called example2.pdf, this time using the "D" option for the sake of the example. This will send the file to the browser and open a dialog box, prompting the user to save the file. 

Fetch data from database in PHP and display in PDF By FPDF

 In this article, you will learn how to fetch data from database and display in PDF using PHP FPDF library.

Today, document security is the most important concern for sharing information over the web. The PDF is the read only document that cannot be altered by users until they have right electronic impression. By utilizing PDF, the associations can put username password on a PDF level to secure document information. There is also demand for producing PDF dynamically increased by the associations, like - generating invoice, salary receipt, visiting card, etc. on single click.

There are several PHP libraries available to generate PDF. In this article, we are using 'FPDF' to generate PDF. F from FPDF stands for Free. This PHP library is used to generate PDF from UTF-8 encoded HTML. The FPDF contains high level functions and rich in features like - image support, color support, page compression, automatic page break and link break. This library supports from PHP version 5.1.

These are the steps to generate PDF to fetch data from database in PHP -


Download FPDF

Download the latest version of the FPDF library from its official website -

FPDF Library

Extract the zip file in your project directory.

Now, let's create a main PHP file 'index.php', that we will call on the browser. At the top of this page, include the FPDF library file -

require('fpdf/fpdf.php');


Make Database Connection

Make sure to provide the right fpdf.php path on your main php file. After this, write the database connection code and make sure to replace 'hostname', 'username', 'password' and 'database' with your database credentials and name.

// Database Connection 
$conn = new mysqli('hostname', 'username', 'password', 'database');
//Check for connection error
if($conn->connect_error){
  die("Error in DB connection: ".$conn->connect_errno." : ".$conn->connect_error);    
}


FPDF Class

Next, instantiate the fpdf class -

$pdf = new FPDF();

The FPDF library has many pre-defined methods, we have used these methods among them -

AddPage() - To add a new page.
SetFont() - To set font.
Cell() - To print a cell.
Ln() - Line break.

Complete Code: index.php

Here, we have merged all codes that explained in details above to generate PDF using PHP FPDF library.

<?php
require('fpdf/fpdf.php');
// Database Connection 
$conn = new mysqli('localhost', 'root', '', 'company');
//Check for connection error
if($conn->connect_error){
  die("Error in DB connection: ".$conn->connect_errno." : ".$conn->connect_error);    
}
// Select data from MySQL database
$select = "SELECT * FROM `empdata` ORDER BY id";
$result = $conn->query($select);
$pdf = new FPDF();
$pdf->AddPage();
$pdf->SetFont('Arial','B',14);
while($row = $result->fetch_object()){
  $id = $row->id;
  $name = $row->name;
  $address = $row->address;
  $phone = $row->phone;
  $pdf->Cell(20,10,$id,1);
  $pdf->Cell(40,10,$name,1);
  $pdf->Cell(80,10,$address,1);
  $pdf->Cell(40,10,$phone,1);
  $pdf->Ln();
}
$pdf->Output();
?>

When, you will call this on the browser, it will look something like this -

PHP generate pdf using fPDF

Monday, March 22, 2021

Single Record In Pdf Using Variable From Query String BY FPDF

 We can generate PDF page by taking data from the query string. This way we will pass variables to our script and using that we will generate our PDF page.

Example

We will create a page to show mark obtained by each student by using a single PHP script. Our PHP script will receive student ID from query sting and generate the mark sheet of the student by taking data from the table.

Displaying list of students in a pdf document:


We will be using one similar student list and then on clicking on the name column of the record we will display the Mark sheet of the student. The link we will click will pass the student number or ID to our script.
IDName
2Max Ruin
3Arnold
4Krish Star
5John Mike
6Alex John
7My John Rob
8Asruid
9Tes Qry
10Big John
<?Php
// connection to database
require "config.php";
require('fpdf.php');
$pdf = new FPDF(); 
$pdf->AddPage();
//collect student id from URL 
$id=$_GET['id'];
if(!is_numeric($id)){
exit;
}
$q="select id,name,class,social,science,math,
(social + science + math) AS total from student3 where id=:id";
$count=$count=$dbo->prepare($q);
$count->bindParam(":id",$id,PDO::PARAM_INT,1);

if($count->execute()){
$row = $count->fetch(PDO::FETCH_OBJ);

$pdf->Image('../images/top2.jpg',10,10);
$pdf->SetFont('Arial','BU',20);
$pdf->SetXY(80,50);
// First header column 
$pdf->Cell(30,10,'MARK SHEET',0,0,L,false);
$pdf->SetY(80);
$pdf->SetFont('Arial','B',16);
$pdf->Cell(30,10,'ID:',0,0,L,false); 
$pdf->SetFont('Arial','',14);
$pdf->Cell(40,10,$row->id,0,1,L,false); 

$pdf->SetFont('Arial','B',16);
$pdf->Cell(30,10,'NAME:',0,0,L,false);  
$pdf->SetFont('Arial','',14);
$pdf->Cell(40,10,$row->name,0,0,L,false); 

$pdf->SetFont('Arial','B',16);
$pdf->Cell(30,10,'CLASS:',0,0,L,false); 
$pdf->SetFont('Arial','',14);
$pdf->Cell(40,10,$row->class,0,0,L,false); 

$pdf->SetY(110);
$pdf->Line(10,100,190,100);
$pdf->SetXY(30,130);
$pdf->SetFont('Arial','UB',16);
$pdf->Cell(100,10,'SUBJECT:',0,0,L,false);  
$pdf->Cell(50,10,'MARK',0,1,L,false);  
$pdf->SetFont('Arial','',14);
$pdf->SetX(30);
$pdf->Cell(100,10,'SOCIAL',0,0,L,false);  
$pdf->Cell(50,10,$row->social,0,1,L,false); 

$pdf->SetX(30);
$pdf->Cell(100,10,'SCIENCE',0,0,L,false);  
$pdf->Cell(50,10,$row->science,0,1,L,false); 

$pdf->SetX(30);
$pdf->Cell(100,10,'MATH',0,0,L,false); 
$pdf->Cell(50,10,$row->math,0,1,L,false); 

$pdf->Line(30,170,150,170);

$pdf->SetX(30);
$pdf->Cell(98,10,'TOTAL',0,0,L,false); 
$pdf->Cell(50,10,$row->total,0,1,L,false);

$pdf->SetXY(160,220);
$pdf->Cell(50,10,'Signature',0,1,L,false);
$pdf->Output();
}else{
print_r($dbo->errorInfo()); 	
}	
?>

Saturday, March 20, 2021

Table Data from Database in PDF BY FPDF

 

PDF Student Table created using PHP

We will take records from our student database and then crate a PDF document by using the data. Records will be displayed in a tabular format.
In above tutorial it is explained how to draw tables, we will use the same concepts to display data with column headers to show the records.
Steps involved are

How to create tables in PDF document by using Cell function

Connect to database,
Run SQL to collect records
Display in data inside a table and generate PDF document.

You can download the ZIP file containing all the above steps. Inside ZIP folder these files are used.

config.php :
Database connection details
index.php :
Shows the records in browser by using Query and PHP Script. ( No PDF is created here )
index-pdf.php :
Display the pdf file with records
sql_dump.txt :
contains SQL dump to create your student table at your local database.
readme.txt :
Help file with links to different solutions.

How to connect and collect the records from table:

Read more about SELECT query here. You can read more on database connection using PHP PDO. The full code to generate PDF document with data from tables is here.
<?Php
require "config.php";//connection to database
//SQL to get 10 records
$count="select * from student LIMIT 0,10";
require('fpdf.php');
$pdf = new FPDF(); 
$pdf->AddPage();

$width_cell=array(20,50,40,40,40);
$pdf->SetFont('Arial','B',16);

//Background color of header//
$pdf->SetFillColor(193,229,252);

// Header starts /// 
//First header column //
$pdf->Cell($width_cell[0],10,'ID',1,0,C,true);
//Second header column//
$pdf->Cell($width_cell[1],10,'NAME',1,0,C,true);
//Third header column//
$pdf->Cell($width_cell[2],10,'CLASS',1,0,C,true); 
//Fourth header column//
$pdf->Cell($width_cell[3],10,'MARK',1,0,C,true);
//Third header column//
$pdf->Cell($width_cell[4],10,'SEX',1,1,C,true); 
//// header ends ///////

$pdf->SetFont('Arial','',14);
//Background color of header//
$pdf->SetFillColor(235,236,236); 
//to give alternate background fill color to rows// 
$fill=false;

/// each record is one row  ///
foreach ($dbo->query($count) as $row) {
$pdf->Cell($width_cell[0],10,$row['id'],1,0,C,$fill);
$pdf->Cell($width_cell[1],10,$row['name'],1,0,L,$fill);
$pdf->Cell($width_cell[2],10,$row['class'],1,0,C,$fill);
$pdf->Cell($width_cell[3],10,$row['mark'],1,0,C,$fill);
$pdf->Cell($width_cell[4],10,$row['sex'],1,1,C,$fill);
//to give alternate background fill  color to rows//
$fill = !$fill;
}
/// end of records /// 

$pdf->Output();
?>

Download and Install script:


Download and Install fpdf class from https://www.fpdf.org/
Keep a copy of fpdf.php file in the same directory
Keep the font directory inside in the same directory.

  • Use the SQL_dump.txt file to create student table in your MySQL database
  • Open config.php file to enter your MySQL login details.
  • Open index.php file to see the records in your borwser ( Not PDF ).
  • Open index-pdf.php file to generate PDF document.
  • Open index1-pdf.php file to generate PDF document with link to breakup of marks.

Connecting database and executing Query:


To manage data we have to connect to MySQL database and execute query to get our date. Here there are two ways to use PHP drivers to connect to MySQL and execute the functions for getting records.

One is using Portable Data Object ( PDO )
Second one is MySQLI ( MysQL Improved )

You can download both the scripts inside the same Zip file. Inside MySQLI folder you can get same scripts with MySQLi connection. ( change the config.php file here also and place fpdf.php with font directory inside this folder)