Create a PDF document template

This document describe how to create your own module to generate different documents that match your needs (for proposals, invoices, etc...) Tutorial is based on commercial proposals used as example but can be used for any type of document.

To know how to build an ODT template, see page Create an ODT document template. Building a PDF template require PHP development knowledge, but not building an ODT template.

= Prerequisite =
 * Dolibarr: 3.0+
 * Knowledge in PHP development

= Find a model near your need = In Dolibarr, test existing models by going to the module setup area and by clicking on the "preview" logo.. Among existing models, find the one that is the nearest of your need. In this example, we suppose it's the template "azur" (corresponding to file pdf_propale_azur.modules.php).

FYI, all models are in htdocs/core/modules, into subdirectory propale for commercial proposals, facture for invoices, commandes for orders, etc...

= Create your new template = For security, we will retain the original models. For the example, we assume we creates a new template we call 'mycompanyblue' and inspired by the template 'azur':
 * Copy and paste file pdf_propale_azur.modules.php
 * Rename the copy into pdf_propale_mycompanyblue.modules.php
 * Edit and make the following changes in the code:
 * 1) Rename 'Class pdf_propale_azur { ' into 'Class pdf_propale_mycompanyblue { '
 * 2) Rename 'Function pdf_propale_azur ($db=0)' into 'Function pdf_propale_mycompanyblue ($db=0)'
 * 3) Rename constant $this->name to match your new template name. For example for 'azur' template, change line '$this->name = "azur";' into '$this->name = "mycompanyblue";'.
 * 4) Save file. Now template is available in the list of models into Dolibarr
 * 5) Test this model (see previous section) before going further ...

= Customize content of your new template = Customize the template created. Still in file pdf_propale_mycompanyblue.modules.php, search function 'Function _pagehead (&$pdf, $fac)'. It manages the display of the header.

Library for PDF manipulation
The library used to create PDF documents in PHP language is called FPDF and can be found into htdocs/includes/tcpdf/tcpdf.class.php. It's also in this class you can find all different methods used to generate different parts of documents.

Templates instantiate this class FPDF and used its method, combined with data of invoice, order, or other kind of data.

We can generraly find the following calls into templates that generated PDF documents:
 * $pdf->SetFont - Define the font to use for the text
 * $pdf->SetXY - Define position (X,Y) for next text that will be output onto page
 * $pdf->MultiCell - Draw a box containing text. Used to output any text
 * $pdf->GetY - Return current Y position
 * $pdf->SetDrawColor - Set the color to use for new text to write - ie black (0,0,0) or white (255,255,255)
 * $pdf->Rect - Drwa a rectanle whose top left corner coordinates ared defineds by two first parameters and bottom right corner is defined by two following parameters that are relative values

Frame of scripts
During the development of version 2.2, the scripts used for generating PDF documents had the following methods (taking as example the model "crabe") inside the class with the model's name:
 * pdf_crabe - Creator of the object pdf
 * write_pdf_file - General method for generating the file. This method calls all the following ones after initializing some variables
 * _pagehead - Method for drawing the heading of the document, including in general the logo, the title of the document (and the date) as well as the frames of the issuer and the addressee of the document
 * _tableau - Method for drawing the details table (products, services,...)
 * _tableau_info - Method for drawing the table containing information list present in the bill
 * _tableau_tot - Method for drawing table of Totals
 * _tableau_versement - Method for drawing table of payment rules
 * _pagefoot - Method for drawing bottom of the page

Insert a logo
With this example: 10=abscissa, 5=ordinate, 60=with of logo
 * Add following instructions
 * If logo is on or outside existing text, remove exisiting text by commenting the code that output the text or by changing its position.

Insert text
Most comme function to use Note: Origin for setXY functions are the top left corner of page.

More information

 * http://www.fpdf.org/?lang=en
 * List of TCPDF's methods: tcpdf.org/doc/code/classTCPDF.html

= Activate your new model = In page Home => Setup => Modules =>
 * activate your module
 * eventually, set it as the default model.

= Troubleshooting =

Q: My PDF template doesn't understand foreign characters, it outputs them as ???
This is probably a font problem, the current font used for generating the PDF cannot handle the foreign characters you are trying to print. So just try to use another set of font.

You will find the fonts used by Dolibarr to print PDF inside your Dolibarr folder.../includes/tcpdf/fonts/

To change the font used for generating PDF, you need to edit the 'main.lang' file of the language you are using (you'll find the file in your Dolibarr.../langs/en_US/main.lang for instance if you use English)


 * Edit the main.lang file
 * Locate the constant FONTFORPDF at the beginning of the file and change the value to FONTFORPDF=dejavusans for instance if you want to use dejavusans. Please note that sometimes FONTFORPDF may be missing, in this case you should add it at the beginning of the file.
 * Save the file and try again to generate your PDF.

If you are unlucky, you can try with more fonts, just go to the TCPDF website sourceforge.net/projects/tcpdf/files/ and download the latest zip package. Then extract only the 'fonts' folder from the zip. Then copy the files in your Dolibarr installation .../includes/tcpdf/fonts/ so you will get more fonts to play with.

Also, please make a backup of your files before to modify.

Alternative if this doesn't work: make sure the Translation class is correctly instanciated and loaded with the correct language inside your PDF templates (stored inside the $langs or $outputlangs variable).

Thank's to Humphrey for the tip.