Difference between revisions of "Create a PDF document template"

From Dolibarr ERP CRM Wiki
Jump to navigation Jump to search
 
(43 intermediate revisions by 13 users not shown)
Line 1: Line 1:
 +
<!-- BEGIN origin interlang links -->
 +
<!-- You can edit this section but do NOT remove these comments
 +
    Links below will be automatically replicated on translated pages by PolyglotBot -->
 +
[[fr:Créer_un_modèle_de_document_PDF]]
 +
[[es:Crear_un_modelo_de_documento_PDF]]
 +
[[zh:创建PDF模板]]
 +
<!-- END interlang links -->
 +
 
{{TemplateDocDevEn}}
 
{{TemplateDocDevEn}}
  
This document describe how to create your own module to generate different documents that match your needs (for proposals, invoices, etc...)
+
This page describes how to create your own document-generation module (for proposals, invoices, etc...)
Tutorial is based on commercial proposals used as example but can be used for any type of document.
+
The tutorial uses Commercial Proposals as an example but the same process is used for any type of document.
 +
 
 +
Building a PDF template requires some PHP knowledge.
 +
An ODT template does not require PHP knowledge. To build an ODT template, see this page [[Create an ODT document template]].
 +
 
 +
=Prerequisites=
 +
 
 +
*Dolibarr: 3.0+
 +
*Knowledge in PHP development
 +
 
 +
 
 +
=Find a document template that is the closest to your requirements=
 +
You may review the existing templates by going to the module setup area, the Commercial Proposals setup in this case, and then clicking on the "preview" logo.
 +
Choose one that is the best match to your needs. In this example, we will use the template "azur" that corresponds to the file
 +
pdf_propale_azur.modules.php
 +
 
 +
All document models are in '''htdocs/core/modules''', in subdirectories, for example
 +
propale for commercial proposals
 +
facture for invoices
 +
commande for orders, etc...
 +
and finally '''doc''' or '''pdf'''.
 +
For instance, proposal templates will be located in '''...core/modules/propale/doc/'''
 +
 
 +
The list of recommended PDF Models :
 +
{| class="wikitable"
 +
!Module
 +
!PDF Model name
 +
!Dolibarr min version
 +
|-
 +
|Shipping
 +
|espadon
 +
|V12
 +
|-
 +
|Order
 +
|eratosthene
 +
|V12
 +
|-
 +
|Invoice
 +
|sponge
 +
|V12
 +
|-
 +
|Proposal/Quotation
 +
|cyan
 +
|V12
 +
|-
 +
|Supplier order
 +
|cornas
 +
|V12
 +
|-
 +
|Delivery
 +
|storm
 +
|V13
 +
|}
 +
 
 +
=Create a new template=
 +
==For an existing core module==
 +
Do not directly modify an existing template.
 +
 
 +
Although it is possible to copy the file of the template used as example into a new name in same directory and edit it to change content it is strongly recommended not to modify any core file or structure(If you want to fix something use the project Github page to propose your changes).
 +
 
 +
Instead use the [[https://wiki.dolibarr.org/index.php?title=Module_development#Module_creation_with_the_module_builder |Module Builder]] available from v12.0 to create your own module even for just a new template.
 +
 
 +
For this example, we will call our new module 'mymodule' and our template 'mycompanyblue', based on the existing template 'cyan':
 +
 
 +
 
 +
*Copy and paste file pdf_cyan.modules.php into custom/mymodule/core/modules/propale/doc
 +
*Rename the copy as pdf_mycompanyblue.modules.php
 +
*Edit the file and make the following changes in the code:
 +
 
 +
#'class pdf_cyan extends ModelePDFPropales' to 'class pdf_mycompanyblue extends ModelePDFPropales'
 +
#'$this->name = "cyan";' to '$this->name = "mycompanyblue";'.
 +
#'$this->description = $langs->trans('DocModelCyanDescription');' to '$this->description = $langs->trans('DocModelMycompanyblueDescription');'.
 +
#Save file.
 +
 
 +
*Edit the file custom/mymodule/core/modules/modMymodule.class.php and make the following changes in the code:
 +
 
 +
#'models' => 0 to 'models' => 1
 +
#Save file.
 +
 
 +
*Activate your new module
 +
 
 +
Now the template will be available in the list of models in the admin settings of proposal.
 +
 
 +
Test this model (see previous section) before going further.
 +
 
 +
==For a new module==
 +
Just use the [[https://wiki.dolibarr.org/index.php?title=Module_development#Module_creation_with_the_module_builder |Module Builder]] AGAIN to create your module. When entering the name of a new object to create, you can also check a checkbox to say that you want to manage documents for such new object. In such a case, two templates will be automatically generated (one ODT template and one PDF template).
 +
 
 +
The templates will be generated with path:
 +
 
 +
*custom/mymodule/core/modules/doc/pdf_standard_myobject.class.php
 +
*custom/mymodule/core/modules/doc/doc_generic_myobject_odt.class.php
 +
 
 +
=Customize content of your new template=
 +
Customize the new template:
 +
 
 +
In file pdf_mycompanyblue.modules.php, look for the function '_pagehead()' function. It is the function that manages the display of the header.
 +
 
 +
Look for the '_pagefooter()' function. It is the function that manages the display of the footer.
  
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.
+
Look for the 'write_file()' function. It is the function that manages the display of the body of PDF.
  
= Prerequisite =
 
* Dolibarr: 3.0+
 
* Knowledge in PHP development
 
  
= Find a model near your need =
+
==Library for PDF manipulation==
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).
+
The library used to create PDF documents in PHP is called TCPDF and can be found in htdocs/includes/tecnickcom/tcpdf/tcpdf.class.php. This class contains the methods used to generate different parts of documents.
  
FYI, all models are in '''htdocs/includes/modules''', into subdirectory propale for commercial proposals, facture for invoices, commandes for orders, etc...
+
Templates instantiate the TCPDF class and use its methods combined with the specific data of the invoice, order etc.
  
= Create your new template =
+
We can generally find the following calls into templates that generate PDF documents:
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:  
 
# Rename 'Class pdf_propale_azur { ' into 'Class pdf_propale_mycompanyblue { '
 
# Rename 'Function pdf_propale_azur ($db=0)' into 'Function pdf_propale_mycompanyblue ($db=0)'
 
# Rename constant $this->name to match your new template name. For example for 'azur' template, change line '$this->name = "azur";' into '$this->name = "mycompanyblue";'.
 
# Save file. Now template is available in the list of models into Dolibarr
 
# Test this model (see previous section) before going further ...
 
  
= Customize content of your new template =
+
*$pdf->SetFont() - ''Define the font to use for the text''
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.
+
*$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() - ''Draw a rectangle whose top left corner coordinates are defined by two first parameters and bottom right corner is defined by two following parameters that are relative values''
  
== Library for PDF manipulation ==
 
The library used to create PDF documents in PHP language is called FPDF and can be found into htdocs/includes/fpdf/fpdf/fpdf.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.
+
==Frame of scripts==
 +
The PHP script used for generating PDF documents had the following methods (taking as example the model "crabe") inside the class with the model's name:
  
We can generraly find the following calls into templates that generated PDF documents:
+
*pdf_crabe() - ''Creator of the object pdf''
* $pdf->SetFont() - ''Define the font to use for the text''
+
*write_pdf_file() - ''General method for generating the file. This method calls all the following ones after initializing some variables''
* $pdf->SetXY() - ''Define position (X,Y) for next text that will be output onto page''
+
*_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''
* $pdf->MultiCell() - ''Draw a box containing text. Used to output any text''
+
*_tableau() - ''Method for drawing the details table (products, services,...)''
* $pdf->GetY() - ''Return current Y position''
+
*_tableau_info() - ''Method for drawing the table containing information list present in the bill''
* $pdf->SetDrawColor() - ''Set the color to use for new text to write - ie black (0,0,0) or white (255,255,255)''
+
*_tableau_tot() - ''Method for drawing table of Totals''
* $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''
+
*_tableau_versement() - ''Method for drawing table of payment rules''
 +
*_pagefoot() - ''Method for drawing bottom of the page''
  
== Frame of scripts ==
+
==Examples of customization==
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:
+
===Insert a logo===
* 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''
 
  
== Examples of customization ==
+
*Add following instructions
=== Insert a logo ===
+
 
* Add following instructions
+
<syntaxhighlight lang="php">
<source lang="php">
 
 
$pdf->Image('\www\htdocs\dolibarr\document\societe\logo.jpg', 10, 5, 60.00);
 
$pdf->Image('\www\htdocs\dolibarr\document\societe\logo.jpg', 10, 5, 60.00);
</source>
+
</syntaxhighlight>
With this example: 10=abscissa, 5=ordinate, 60=with of logo
+
With this example: 10=abscissa, 5=ordinate, 60=width of logo
* 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 ===
+
*If the logo is on or outside existing text, remove existing text by commenting the code that outputs the text or by changing its position.
Most comme function to use
+
 
<source lang="php">
+
===Insert text===
 +
Most common function to use
 +
<syntaxhighlight lang="php">
 
$pdf->setX(float a); // set current x position
 
$pdf->setX(float a); // set current x position
 
$pdf->setY(float b); // set current y position
 
$pdf->setY(float b); // set current y position
Line 71: Line 161:
 
$pdf->SetFont('Arial','B',14); // fixe la police, le type ( 'B' pour gras, 'I' pour italique, '' pour normal,...)
 
$pdf->SetFont('Arial','B',14); // fixe la police, le type ( 'B' pour gras, 'I' pour italique, '' pour normal,...)
 
$pdf->MultiCell(60, 8, 'Mon texte", 0, 'L'); // imprime 'Mon texte' avec saut de ligne
 
$pdf->MultiCell(60, 8, 'Mon texte", 0, 'L'); // imprime 'Mon texte' avec saut de ligne
</source>
+
</syntaxhighlight>
 
Note: Origin for setXY functions are the top left corner of page.
 
Note: Origin for setXY functions are the top left corner of page.
  
== More information ==
+
===Add a PDF Annotation (comment)===
http://www.fpdf.org/?lang=en
+
''Left side of the page around the middle:''
 +
<syntaxhighlight lang="php">
 +
$pdf->Annotation(102, 202, 10, 10, "this is the comment text", array('Subtype'=>'Text', 'Name' => 'Comment', 'T' => 'this is comment author', 'Subj' => 'this is comment title', 'C' => array(255, 255, 0)));
 +
</syntaxhighlight>
  
= Activate your new model =
+
''Right side of the page around the middle:''
 +
<syntaxhighlight lang="php">
 +
$pdf->Annotation(202, 102, 10, 10, "this is the comment text", array('Subtype'=>'Text', 'Name' => 'Comment', 'T' => 'this is comment author', 'Subj' => 'this is comment title', 'C' => array(255, 255, 0)));
 +
</syntaxhighlight>
 +
 
 +
===Add Complementary Attribute (extrafiled)===
 +
A dedicated page give you some advises how to integrate complementary attributes (extrafields) into PDF models of Dolibarr [[Add Extrafields on PDF Models]]
 +
 
 +
==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 =>
 
In page Home => Setup => Modules =>
* activate your module
+
 
* eventually, set it as the default model.
+
*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 font.
 +
 
 +
You will find the fonts used by Dolibarr to print PDF inside your Dolibarr folder.../includes/tecnickcom/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/tecnickcom/tcpdf/fonts/ so you will get more fonts to play with.
 +
 
 +
Also, please make a backup of your files modification.
 +
 
 +
Alternative if this doesn't work: make sure the Translation class is correctly instantiated and loaded with the correct language inside your PDF templates (stored inside the $langs or $outputlangs variable).
 +
 
 +
Thanks to Humphrey for the tip.

Latest revision as of 23:55, 23 January 2025


This page describes how to create your own document-generation module (for proposals, invoices, etc...) The tutorial uses Commercial Proposals as an example but the same process is used for any type of document.

Building a PDF template requires some PHP knowledge. An ODT template does not require PHP knowledge. To build an ODT template, see this page Create an ODT document template.

Prerequisites

  • Dolibarr: 3.0+
  • Knowledge in PHP development


Find a document template that is the closest to your requirements

You may review the existing templates by going to the module setup area, the Commercial Proposals setup in this case, and then clicking on the "preview" logo. Choose one that is the best match to your needs. In this example, we will use the template "azur" that corresponds to the file pdf_propale_azur.modules.php

All document models are in htdocs/core/modules, in subdirectories, for example propale for commercial proposals facture for invoices commande for orders, etc... and finally doc or pdf. For instance, proposal templates will be located in ...core/modules/propale/doc/

The list of recommended PDF Models :

Module PDF Model name Dolibarr min version
Shipping espadon V12
Order eratosthene V12
Invoice sponge V12
Proposal/Quotation cyan V12
Supplier order cornas V12
Delivery storm V13

Create a new template

For an existing core module

Do not directly modify an existing template.

Although it is possible to copy the file of the template used as example into a new name in same directory and edit it to change content it is strongly recommended not to modify any core file or structure(If you want to fix something use the project Github page to propose your changes).

Instead use the [|Module Builder] available from v12.0 to create your own module even for just a new template.

For this example, we will call our new module 'mymodule' and our template 'mycompanyblue', based on the existing template 'cyan':


  • Copy and paste file pdf_cyan.modules.php into custom/mymodule/core/modules/propale/doc
  • Rename the copy as pdf_mycompanyblue.modules.php
  • Edit the file and make the following changes in the code:
  1. 'class pdf_cyan extends ModelePDFPropales' to 'class pdf_mycompanyblue extends ModelePDFPropales'
  2. '$this->name = "cyan";' to '$this->name = "mycompanyblue";'.
  3. '$this->description = $langs->trans('DocModelCyanDescription');' to '$this->description = $langs->trans('DocModelMycompanyblueDescription');'.
  4. Save file.
  • Edit the file custom/mymodule/core/modules/modMymodule.class.php and make the following changes in the code:
  1. 'models' => 0 to 'models' => 1
  2. Save file.
  • Activate your new module

Now the template will be available in the list of models in the admin settings of proposal.

Test this model (see previous section) before going further.

For a new module

Just use the [|Module Builder] AGAIN to create your module. When entering the name of a new object to create, you can also check a checkbox to say that you want to manage documents for such new object. In such a case, two templates will be automatically generated (one ODT template and one PDF template).

The templates will be generated with path:

  • custom/mymodule/core/modules/doc/pdf_standard_myobject.class.php
  • custom/mymodule/core/modules/doc/doc_generic_myobject_odt.class.php

Customize content of your new template

Customize the new template:

In file pdf_mycompanyblue.modules.php, look for the function '_pagehead()' function. It is the function that manages the display of the header.

Look for the '_pagefooter()' function. It is the function that manages the display of the footer.

Look for the 'write_file()' function. It is the function that manages the display of the body of PDF.


Library for PDF manipulation

The library used to create PDF documents in PHP is called TCPDF and can be found in htdocs/includes/tecnickcom/tcpdf/tcpdf.class.php. This class contains the methods used to generate different parts of documents.

Templates instantiate the TCPDF class and use its methods combined with the specific data of the invoice, order etc.

We can generally find the following calls into templates that generate 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() - Draw a rectangle whose top left corner coordinates are defined by two first parameters and bottom right corner is defined by two following parameters that are relative values


Frame of scripts

The PHP script 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

Examples of customization

  • Add following instructions
$pdf->Image('\www\htdocs\dolibarr\document\societe\logo.jpg', 10, 5, 60.00);

With this example: 10=abscissa, 5=ordinate, 60=width of logo

  • If the logo is on or outside existing text, remove existing text by commenting the code that outputs the text or by changing its position.

Insert text

Most common function to use

$pdf->setX(float a); // set current x position
$pdf->setY(float b); // set current y position
$pdf->setXY(float a,float b); // fixe les positions x et y courantes
$pdf->SetTextColor(0,0,200); // fixe la couleur du texte
$pdf->SetFont('Arial','B',14); // fixe la police, le type ( 'B' pour gras, 'I' pour italique, '' pour normal,...)
$pdf->MultiCell(60, 8, 'Mon texte", 0, 'L'); // imprime 'Mon texte' avec saut de ligne

Note: Origin for setXY functions are the top left corner of page.

Add a PDF Annotation (comment)

Left side of the page around the middle:

$pdf->Annotation(102, 202, 10, 10, "this is the comment text", array('Subtype'=>'Text', 'Name' => 'Comment', 'T' => 'this is comment author', 'Subj' => 'this is comment title', 'C' => array(255, 255, 0)));

Right side of the page around the middle:

$pdf->Annotation(202, 102, 10, 10, "this is the comment text", array('Subtype'=>'Text', 'Name' => 'Comment', 'T' => 'this is comment author', 'Subj' => 'this is comment title', 'C' => array(255, 255, 0)));

Add Complementary Attribute (extrafiled)

A dedicated page give you some advises how to integrate complementary attributes (extrafields) into PDF models of Dolibarr Add Extrafields on PDF Models

More information

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 font.

You will find the fonts used by Dolibarr to print PDF inside your Dolibarr folder.../includes/tecnickcom/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/tecnickcom/tcpdf/fonts/ so you will get more fonts to play with.

Also, please make a backup of your files modification.

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

Thanks to Humphrey for the tip.