Image de l'article Créer un fichier PDF avec PHP

Commentaires sur l'article Créer un fichier PDF avec PHP

#1

Par Olivier O. à 11h07 :

Oki, bien noté, merci Patrice.

#2

Par matrix128bit à 09h30 :

J'ai beaucoup appréciez la description de création de fichiers pdf mais j'aurai voulu garder le conctact avec afin d'avoir plus d'information si je peux me permettre de dire formation help me

#3

Par Patrice à 17h38 :

Bonjours matrix128bit,

Que voulez savoir de plus ? Je ne fais pas de formation, je n'ai pas de temps pour ça.
Le mieux est de prendre du temps et de tester petit à petit pour arriver à ce que l'on veux comme résultat.

#4

Par AlexandreRideau à 11h44 :

Bonjour,

Tout d'abord merci pour ce tuto très bien construit et pour ce code bien utile !
Je rencontrecependant plusieurs problèmes ...

Le premier étant que je ne comprend pas trop l'URL que l'on doit appeler, est-ce :
http://lesite.fr/index.php?id=0&download=nomdufichier

Le second est que lorsque j'appelle cette URL j'obtient une erreur php :

Notice: Undefined variable: yMax in C:\wamp\www\pdf\facturePDF.php on line 298


Encore une fois merci pour votre aide :D

#5

Par Patrice à 15h47 :

Bonjour Alexandre,

Content que cet exemple puisse servir.

Je ne suis pas sûr d'avoir compris la question à propos de l'URL, mais il n'y en a pas à proprement parler. Je vous fourni une classe PHP que vous devez inclure et initialiser dans un fichier PHP.

<?php
// importe la class facturePDF qui va elle-même charger FPDF
require('facturePDF.php');
?>

Quand à l'erreur vous pouvez la corriger en ajouter $yMax = 0;
Voici la fonction complète corrigée :

function Header(){
$yMax = 0;
if(!empty($this->logoUrl)){
$this->Image($this->logoUrl, $this->logoPosX, $this->logoPosY, $this->logoWidth);
$this->Ln(12);
}
// elements d'entete
foreach($this->elementLst['header'] as $v){
$yMax = max($yMax, $this->prepareLine($v['text'], $this->template[$v['id']]));
}
// entete du tableau
if(!empty($this->productHead)){
$this->SetY($yMax);
$tplt = $this->template['productHead'];
$this->buildLine($this->productWidth, $tplt['lineHeight'], $this->productHead, $this->productHead, $tplt, $tplt['color'], $tplt['backgroundColor']);
}
}

Vous ne devriez plus avoir d'erreur à présent.

#6

Par AlexandreRideau à 16h09 :

Merci beaucoup Patrice, je confirme que celà fonctionne correctement maintenant.
Excusez-moi pour le dérangement, je pense que j'aurais pu corriger ce bug tout seul ...


Je rencontre cependant un problème que j'ai déjà rencontré sur d'autre script fpdf, lorsqu'il y à trop de lignes pour le tableau de la première page, les suivantes se créent sur la page d'après.
Le problème étant que ces lignes "débordent" sur le footer et je n'arrive pas à comprendre comment les en empêcher ...

En tout cas merci pour votre première réponse trés rapide !

xD

#7

Par AlexandreRideau à 09h53 :

* :D

#8

Par Patrice à 14h29 :

Bonjour Alexandre,

Effectivement il doit y avoir des ratés au passage d'une nouvelle page, la classe ajoute les lignes les unes après les autres, je l'avais conçu pour des factures d'une page.

Il faudrait modifier un peu la fonction buildPDF pour vérifier s'il y a la place pour ajouter une ligne. Pour cela il faudrait calculer la hauteur du pied de page et l'enregistrer dans une variables. Puis faire la soustraction.

Vous pensez y arriver ?

#9

Par AlexandreRideau à 14h43 :

Bonjour Patrice,

En effet c'est bien ce que je pensais, mais j'avoue galérer un peut n'étant pas un "pro" de fpdf ...

Je ne comprend pas trop comment faire pour calculer la hauteur du pied de page.


J'essaye aussi d'afficher le numéro de page en haut à droite là où est écrit "Page" mais n'y arrive pas non plus.


En tout cas merci pour toute votre aide :-)

#10

Par Patrice à 15h05 :

Pour avoir le numéro de page il faut utiliser la fonction PageNo()
<?php
require('fpdf.php');
$pdf = new FPDF();
$pdf->Cell(0, 10, 'Page '.$pdf->PageNo(), 0, 0, 'C');
$pdf->Output();
?>

Vous pouvez utiliser le texte '{nb}' pour afficher le nombre de page total du document.
$pdf->Cell(0, 10, 'Page '.$pdf->PageNo(.'/{nb}'), 0, 0, 'C');


Je vais corriger le bug des multi-pages dans les semaines prochaines parce que j'en aurais besoin sur un autre projet ;-)

#11

Par AlexandreRideau à 15h16 :

Ok cool.

Bon si jamais j'y arrive avant je vous le dirais.

Merci à vous :-)

#12

Par Adrien à 12h25 :

Bonjour Patrice,

Merci pour ce tuto !

Des indications particulières pour faire apparaitre des bordures autour des tableaux créés dans le pdf ?

J'avoue être en train de me battre avec en ce moment, et je vois que tu avais l'intention de partager des informations à ce propos.

Est-ce toujours d'actualité ?

Merci à toi !

#13

Par Patrice à 12h43 :

Bonjour Adrien,

Je n'ai pas travaillé sur ce point depuis.
Il faut modifier la fonction buildLine(), à la ligne 228.
C'est ici que le fond de la cellule est dessiné.
Tu peux remplacer :
$this->Rect($aTplt['margin'][3], $this->GetY()+$aTplt['margin'][0], $aW+$aTplt['padding'][1]+$aTplt['padding'][3], $aH+$aTplt['padding'][0]+$aTplt['padding'][2], 'F');

Par : $this->Rect($aTplt['margin'][3], $this->GetY()+$aTplt['margin'][0], $aW+$aTplt['padding'][1]+$aTplt['padding'][3], $aH+$aTplt['padding'][0]+$aTplt['padding'][2], 'D');

Plutôt que de remplir ('F'), le rectangle va être dessiné ('D')

Plus d'info :
http://www.fpdf.org/en/doc/rect.htm

C'est du bricolage mais c'est pour l'idée ;-)

A noter que je n'ai pas testé, il faut peut-être modifier l'épaisseur et / ou la couleur du trait.

#14

Par Adrien à 15h47 :

Je te remercie beaucoup pour cette réponse, je vais essayer tout ça :)

#15

Par Adrien à 16h10 :

Je vois donc à peu près le principe.

En fait, souhaitant mettre un espèce de quadrillage pour une facture, je pense que le mieux est de repartir sur la définition des cellules qui composent le tableau le représentant.

#16

Par Patrice à 11h41 :

Oui dans ce cas il faut modifier le code un tout petit plus loin.
Ligne 236. C'est dans cette boucle foreach que les cellules d'une ligne de produit sont affichées.

D'ailleur la fonction MultiCell permet de dessiner une bordure :
http://www.fpdf.org/fr/doc/multicell.htm

Mais tu perds la notion de padding et margin je pense.

#17

Par Adrien à 14h14 :

En effet.

Je pense que le mieux est de repartir sur une création de cellules individuelles peut-être.

#18

Par khalid btb à 03h44 :

j'essaye de compiler le fichiers mais toujours un probléme au niveau de fichier faturePDF:
Fatal error: Call to undefined method facturePDF::FPDF() in C:\xampp\htdocs\TD\facturePDF.php on line 29

#19

Par Patrice à 09h17 :

Bonjour khalid btb,

La librairie FPDF est correctement chargée ?
La ligne 29 "$this->FPDF();" c'est l'appel au constructeur.

#20

Par alf à 19h23 :

Bonjour,

J'ai aussi le message d’erreur suivant :

Call to undefined method facturePDF::FPDF()

je n'arrive pas à trouver le problème merci de bien vouloir me conseiller ...

#21

Par Patrice à 19h40 :

Bonsoir alf,

Question bête, mais le fichier est correctement chargé ?
Ligne 1 tu peux ajouter un simple echo "FICHIER CHARGÉ";

#22

Par Patrice à 19h42 :

C'est un serveur Microsoft ou Apache ?

#23

Par Raph à 12h09 :

Pour l'erreur de la ligne 29, c'est parce qu'il faut appeler le constructeur parent de cette manière :

parent::__construct();

remplacez donc :
$this->FPDF();
par :
parent::__construct();


Merci à Patrice pour ce super tuto !

#24

Par Patrice à 21h56 :

Merci Raph, j'ai corrigé les fichiers pour prendre en compte cette remarque.

#25

Par lansana à 15h08 :

Bonjour Patrice,
Permet moi de te remercier pour ce super tuto.
Ma question est la suivante : avec cette bibliothèque est ce qu'on peut sécuriser par mot de passe le fichier pdf produit.
Pour la lecture, l'impression.... qu'on demande un mot de passe ?
Si cette bibliothèque ne le fait pas connaissez vous une autre bibliothèque qui peut le faire ?

Merci d'avance

#26

Par Patrice à 14h28 :

Bonjour lansana,

Oui c'est possible, voir ce lien :
http://www.fpdf.org/en/script/script37.php

#27

Par Guillaume à 18h30 :

Bonjour Patrice,

Il faut simplement excuser mon côté un peu débutant : je pense avoir fait tout ce qu'il fallait en ayant notamment chargé la version fpdf 1.81...
Ai fait le correctif $yMax = 0; car j'avais la même erreur que Alexandre.

j'ai cette erreur que je ne parviens pas à débuger par moi-même :
Notice: Undefined index: download in C:\...\facturePDF\index.php on line 55

Est-ce que tu as une solution ?

Grand Merci par avance et très beau tuto

Guillaume

#28

Par Guillaume à 18h38 :

Patrice,

Toutes mes excuses... je n'avais pas assez fouillé... j'ai trouvé par moi-même une solution en relisant ton tuto au bon endroit...

Grand Merci encore...

Guillaume

#29

Par Patrice à 19h38 :

Bien joué Guillaume :-)

#30

Par Stephan à 16h27 :

Bonjour et merci pour ce magnifique tuto qui m'a sauvé la vie:-).

Je n'arrive pas à afficher les bordures des tableaux.
est ce que vous pouvez m'aider ou m'orienter ?

merci d'avance.

#31

Par Patrice à 17h35 :

Bonsoir Stephan,

FPDF permet de dessiner des bordures sur les cellules :
http://www.fpdf.org/en/doc/cell.htm

Mais je n'ai pas testé.
Si ça ne fonctionne pas, vous pouvez essayer de dessiner un rectangle autour des cellules avec rect :
http://www.fpdf.org/fr/doc/rect.htm

#32

Par maliwari à 16h34 :

Bonjour,
tout en esperant que quelqu'un suit ce forum.
j'ai quelques erreurs dans la generation de ma facture..
- Notice: Undefined offset: 2 in C:\wamp\www\PROGEST\facturePDF\facturePDF.php on line 237
- Notice: Undefined offset: 2 in C:\wamp\www\PROGEST\facturePDF\facturePDF.php on line 241
- Fatal error: Uncaught exception 'Exception' with message 'FPDF error: Some data has already been output, can't send PDF file (output started at C:\wamp\www\PROGEST\facturePDF\facturePDF.php:241)' in C:\wamp\www\PROGEST\facturePDF\fpdf.php on line 271
- Notice: Undefined index: download in C:\wamp\www\PROGEST\facturePDF\index.php on line 78.
SI quelqu'un a une idée s'il vous plait!

#33

Par Patrice à 17h08 :

Bonjour maliwari,

Première et deuxième erreur : ligne 237 et 241 ça vient de $aHeader[$k]['width'] qui n'est pas définit. Il faut donc le définir avec productHeaderAddRow();
La troisième erreur c'est normal. Des entêtes ont déjà été envoyé, donc on ne peut pas les rechanger.
L'erreur à la ligne 78 d'index.php je ne sais pas. A toi de la trouver et de la corriger ;-)

#34

Par maliwari à 08h34 :

Bonjour Patrice,
Merci pour la réponse ...
Je vais essayer de corriger les deux premières erreurs.
Pour le problème de la ligne 78, je ne sais vraiment pas comment le gérer car dans certaines versions de wampserver ça fonctionne(ancienne version, 2.0.5 par exple) mais ça marche pas avec la version 3.0.6 et je ne sais pas pourquoi?
Même pour les gabarits j'avais les mêmes soucis au niveau $_GET['id']. Des que je change de version de wampserver tous ces problèmes ont apparu. Avec mon ancienne version, tout se passe a merveille.
Merci pour le coup de main!

#35

Par Patrice à 10h18 :

Est-ce que tu peux poster la ligne 78 ?

#36

Par maliwari à 10h48 :

$pdf->Output('Facture.pdf', $_GET['download']?'D':'I');

#37

Par maliwari à 11h05 :

Même avec les lignes 237 et 241 c'est la même chose. Initialement tout marchait avec wampserver 2.0.5, j'arrivais à produire ma facture sans soucis ni de bug. Mais, une fois migrer sur 3.0.6 les erreurs ont commencées... Sinon, les productHeaderAddrow(), sont bien définis et s'affiche bien avec l'ancienne version de wampserver et je ne sais pas pourquoi ça ne marche pas avec la version 3.0.6.
Merci

#38

Par Patrice à 11h42 :

Il faut ajouter des vérifications. Undefined offset, ça veut dire qu'il ne trouve pas l'index demandé dans l'array. Pour le corriger c'est facile, il faut vérifier si la valeur existe avec isset :


$pdf->Output('Facture.pdf', isset($_GET['download']) ? 'D':'I');

Reste à faire les deux autres lignes de la même manière. Vérifier si la valeur existe avec isset et, si ce n'est pas le cas, choisir une valeur par défaut.

#39

Par maliwari à 13h48 :

Merci. Je vais essayer ça tout de suite et vous revenir...
Merci infiniment !

#40

Par maliwari à 14h28 :

Salut Patrice,
Je viens de régler le problème de download avec issset, avec tes complications j'ai compris que j'avais fait une erreur au $pdf->totalAdd qui est de dimension deux, et que j'avais mis trois pour pourvoir ajouter la devise, ma seconde valeur vient d'une base de données, maintenant ça marche(la facture s'affiche en pdf)mais pas bien.
J'ai la facture mais j'ai perdu la mise en forme(l'affichage est devenu buzzarre, toutes les données commence en haut de la feuille), probablement à cause des gabarits que mon système ne connaissait pas à travers le intval et $_GET['id']...
Je vais voir claire tête reposé et vous revenir en cas de difficulté

#41

Par maliwari à 20h50 :

Salut!
Tout marche Nickel maintenant en mettant les isset où tu as montré...
Tout est parfait, merci infiniment !

#42

Par EchoTango à 23h27 :

Bonjour, j'essaye d'accéder à votre interface FacturePDF via Javascript (AJAX) mais au retour je n'ai que la sortie imprimante (postscript?) et non le pdf. Le code est ci-dessous. J'ai essaye d'envoyer un header avec "xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");" mais le résultat est le même.
Evidemment index.php fonctionne très bien.
Y aurait-il un moyen ? J'envoie ces factures par mail ensuite.
Merci d'avance.

<html>
<script>
xmlhttp = new XMLHttpRequest();
myUrl="index.php?client="+"NOM DE MON CLIENT";
xmlhttp.open("GET",myUrl,true);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
txt2retour=this.responseText;
}
}
</script>
</html>

#43

Par Patrice à 00h01 :

Bonsoir EchoTango,

Je pense que le problème vient de cette ligne :
$pdf->Output('Facture.pdf', $_GET['download'] ? 'D':'I');

La fonction output de FPDF attend trois paramètres de sortie :
1- le chemin
2- le mode
I: envois le PDF vers le navigateur pour affichage ou téléchagement
D: force le chargement du PDF
F: enregistrer le fichier
S: renvoit le document sous forme de string
3- l'encodage

Plus d'info http://www.fpdf.org/en/doc/output.htm

Il faudrait soit enregistrer le PDF sur le serveur et renvoyer le chemin en retour ou renvoyer le document sous forme de string.

#44

Par EchoTango à 20h46 :

Merci pour cette réponse. En effet j'ai regardé ces paramètres et ai fait des essais en deux modes 1) exécution directe 2) via JS xmlhttp sachant que mon objectif est bien le mode 2.

En mode 1 le paramètre F crée bien un pdf sur le serveur. Le D crée un pdf local mais m'oblige à valider le répertoire que je ne veux pas faire. Donner le nom du pdf avec répertoire ne change rien. La paramètre S affiche le postscript.

En mode 2, j'arrive parfaitement à créer le pdf sur le serveur paramètre F (donc mon JS appelle le php qui crée le pdf). Le D ne fait rien (ne crée pas le fichier, ne me demande pas de valider le répertoire). Le S c'est pareil : postscript.

Evidemment, je peux télécharger les pdf qui sont créés sur le serveur en local.
Mais maintenant je dois créer mes factures avec fpdf. Ce qui parait évident.

Mon problème c'est que je les crée déjà mes factures avec JS/mysqli. Je peux les imprimer et les mettre à la poste sans problème. Seulement, sur 50 factures mensuelles la moitié est envoyée en pdf par mail.

Et c'est la question, comment créer ces 25 pdf indépendants (donc avec des noms individuels) depuis JS sans intervention manuelle.

Comme un certain l'aurait dit , être ou ne pas être.

Merci.




#45

Par EchoTango à 13h47 :

J'ai opté pour la solution suivante :
J'utilise dompdf pour créer la facture en pdf (en utilisant le modèle de facture que j'avais déjà mais sans lui passer donc le html en entier).
Pour les données mysqli, je les passe dans une matrice JSON avec AJAX mode POST, la partie lignes de factures étant évidemment variable d'un client à l'autre.
Ce même php crée le pdf avec un nom de fichier adéquat et l'envoie par mail au client.
Physiquement les factures sont sur le serveur, et je les liste par glob puis les récupère par readfile pour stockage local.
Voilà.
(pour la petite histoire, j'avais déjà écrit cette application il y a 10 ans et qui fonctionne à merveille, facile à mettre à jour et maintenir ..... en EXCEL VBA :-)

#46

Par Patrice à 11h04 :

Super, merci pour le retour :-)

Ajouter votre commentaire

Votre adresse ne sera pas affichée.

Elle sert à vous envoyer une notification.

 

Image Viewer