Create a PDF document template: Difference between revisions

(Created page with '{{TemplateDocDevEn}} {{ToTranslate}} Ce document décrit comment créer son propre modèle de génération de document PDF afin de personnaliser ses documents (propales, factures...')
 
 
(74 intermediate revisions by 16 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}}
{{ToTranslate}}
Ce document décrit comment créer son propre modèle de génération de document PDF afin de personnaliser ses documents (propales, factures, etc...)
Il se base sur les propositions commerciales comme exemple mais s'applique à tout type de document.


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 :
{| 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.
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==
===Insert a logo===
*Add following instructions
<syntaxhighlight lang="PHP">
$pdf->Image('\www\htdocs\dolibarr\document\societe\logo.jpg', 10, 5, 60.00);
</syntaxhighlight>
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
<syntaxhighlight lang="PHP">
$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
</syntaxhighlight>
Note: Origin for setXY functions are the top left corner of page.


= Trouver le modèle existant le plus proche =
===Add a PDF Annotation (comment)===
Dans Dolibarr tester les modèles existants en activant tous les modèles existants dans la configuration du module puis en générant et visualisant un document brouillon pour chacun d'entre eux.
''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>


Parmi ceux existant, noter le modèle le mieux adapté aux besoins. Dans cet exemple, c'est le modèle bleu (correspondant au fichier pdf_propale_bleu.modules.php).
''Right side of the page around the middle:''
Rem: Pour info, tous les modèles de propales sont dans \includes\modules\propale si vous êtes sous Windows et /includes/modules/propale si vous êtes sous Unix.
<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>


= Créer le nouveau modèle =
===Add Complementary Attribute (extrafiled)===
Par sécurité, on conservera les modèles d'origine. Pour l'exemple, on part du principe qu'on crée un nouveau module de proposition commercial qu'on nommera 'masocietebleu' et qui s'inspire du module 'bleu':
A dedicated page give you some advises how to integrate complementary attributes (extrafields) into PDF models of Dolibarr [[Add Extrafields on PDF Models]]
* copier-coller pdf_propale_bleu.modules.php
* renommer la copie en pdf_propale_masocietebleu.modules.php
* l'éditer et faire les modifs suivantes dans le code:
# Renommer 'Class pdf_propale_bleu { '    en 'Class pdf_propale_masocietebleu { '  (ligne 24)
# Renommer 'Function pdf_bleu($db=0)' en 'Function pdf_propale_masocietebleu($db=0)'  (ligne 26)
# Sauvegarder : le modèle 'masocietebleu' est disponible dans la liste des modèles de propales de Dolibarr
* Tester ce modèle (Voir A) avant d'aller plus loin...


= Personnaliser =
==More information==
Personnaliser le modèle créé.
Toujours dans pdf_propale_masocietebleu.modules.php, chercher la fonction 'Function _pagehead(&$pdf, $fac)' (vers la ligne 306). C'est elle qui gère l'affichage de l'entête. 


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


== Librairie de création ==
=Activate your new model=
In page Home => Setup => Modules =>


La librairie utilisée pour la création de documents en PDF se nomme FPDF et peut être trouvée dans htdocs/includes/fpdf/fpdf/fpdf.class.php. C'est également dans cette classe que l'on trouve les nombreuses méthodes utilisées pour générer les différents éléments des documents.
*activate your module
*eventually, set it as the default model.


Les modèles eux-même instancient la classe FPDF et utilisent ensuite ses méthodes, combinées avec les données d'une facture, d'une commande ou d'autres types de données.


On retrouve généralement les appels suivants dans les scripts de création de documents:
=Troubleshooting=
* $pdf->SetFont() - ''Désigne la fonte à utiliser pour le texte qui suivra''
* $pdf->SetXY() - ''Désigne le point de départ pour dessiner le prochain texte en coordonnées X,Y qui sont exprimées en millimètres de la page''
* $pdf->MultiCell() - ''Dessine une boîte pouvant contenir du texte, et dont on doit d'abord donner la largeur et la hauteur - très utilisée''
* $pdf->GetY() - ''Renvoie la position courante en Y''
* $pdf->SetDrawColor() - ''Désigne la couleur à utiliser pour le prochain texte à écrire - généralement noir (0,0,0) ou blanc (255,255,255)''
* $pdf->Rect() - ''Dessine un rectangle dont le coin supérieur gauche est au point indiqué par les deux premiers paramètres et le coin inférieur droit utilise les deux derniers paramètres en mode relatif aux deux premiers''


==Q: My PDF template doesn't understand foreign characters, it outputs them as ???==


== Structure des scripts ==
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.


Les scripts de génération des documents PDF, au moment du développement de la version 2.2, disposent des méthodes suivantes (prenant pour exemple le modèle "crabe") au sein de la classe du nom du modèle:
You will find the fonts used by Dolibarr to print PDF inside your Dolibarr folder.../includes/tecnickcom/tcpdf/fonts/
* pdf_crabe() - ''Constructeur de l'objet pdf''
* write_pdf_file() - ''Méthode générale pour la génération du fichier. Cette méthode appelle toute les suivantes après avoir initialisé quelques variables''
* _pagehead() - ''Méthode de dessin de l'en-tête du document, incluant généralement le logo, le titre du document (et la date) ainsi que les cadres de l'émetteur et du destinataire du document''
* _tableau() - ''Méthode de dessin du tableau de détails (produits, services, etc)''
* _tableau_info() - ''Méthode de dessin du tableau reprenant une liste d'informations sur la facture''
* _tableau_tot() - ''Méthode de dessin du tableau des totaux''
* _tableau_versement() - ''Méthode de dessin du tableau des règles de versement''
* _pagefoot() - ''Méthode de dessin du pied de page''


   
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)
== Insertion d'un logo ==
* Chercher la séquence suivante:
$pdf->SetXY(10,5);
if (defined("FAC_PDF_INTITULE"))
{
    $pdf->SetTextColor(0,0,200);
    $pdf->SetFont('Arial','B',14);
    $pdf->MultiCell(60, 8, FAC_PDF_INTITULE, 0, 'L');
* Ajouter l'instruction:
    $pdf->Image('\www\htdocs\dolibarr\document\societe\logo.jpg', 10, 5,60.00);
* Mettre en commentaire l'instruction d'affichage de la variable FAC_PDF_INTITULE


== Modification des constantes affichées ==
*Edit the main.lang file
Principales fonctions utilisées
*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.
    $pdf->setX(float a); fixe la position x courante
*Save the file and try again to generate your PDF.
    $pdf->setY(float b); fixe la position y courante
    $pdf->setXY(float a,float b); fixe les positions x et y courantes
    (rappel: l'origine est le coin supérieur gauche)
    $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, FAC_PDF_INTITULE, 0, 'L'); imprime la variable  FAC_PDF_INTITULE avec saut de ligne
(info: Il semble que Dolibarr gère un certain nombre de constantes dans Accueil => Configuration => System => Constantes. Mais ça ne fonctionne pas sur ma config ...).


== Pour plus d'infos ==
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.
http://www.fpdf.org/?go=script&id=2 et aller sur 'accueil'


== Le résultat ==
Also, please make a backup of your files modification.
Réalisation ozit: http://www.adytek.com/PR040123.pdf


= Choisir un modèle par défaut dans Dolibarr =
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).
Dans Accueil => Configuration => proposition commerciale:
* on affiche les modèles,
* on indique ceux qui doivent être actifs,
* on précise le modèle proposé par défaut.


= Merci =
Thanks to Humphrey for the tip.
Merci à David, Florent et surtout ozit pour leur aide.

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.