Programmierung Thomas Weise

twPdf - Rechnung

PDF-Rechnung mit PHP erzeugen Demo

von Thomas Weise ( Blog)

Dieser Artikel zeigt die Erzeugung eines PDF-Dokuments am Beispiel einer Rechnung. Verwendet wird dabei die Klasse 'FPDF' und eine neu erstellte Klasse 'TwPdfRechnung'. Blog.

Ausgangslage

Diese Anleitung beschränkt sich nur auf die technische Realisierung der PDF-Erzeugung. Die Rechnungsdaten, wie Kunden- und Firmenanschrift und die einzelnen Positionen sind fest in der Datei als Variablen angegeben, um dieses Beispiel nicht zu gestalten. Wie diese festen Variablen auch noch als Benutzereingaben realisierbar sind, könnte eventuell bei entsprechender Nachfrage in einem Folge-Tutorial erklärt werden. Für die Ausführung des folgenden Beispiels ist es erforderlich, daß auf dem Webserver PHP5 verfügbar ist. Falls PHP5 nicht verfügbar ist, sei auf den ersten Teil des Tutorials verwiesen, in dem unter Anderem beschrieben ist, wie die Beispiele auf auf einem Webserver mit älterem PHP lauffähig sind.

Wir gehen davon aus, dass Sie den ersten Teil des Tutorials gelesen haben und folgende Verzeichnisstruktur auf Ihrem Webserver vorliegen haben.

Screenshot

  • Legen Sie nun eine Datei rechnung.php im Projektverzeichnis an und kopieren den Inhalt folgender Datei dort hinein. rechnung.php kopieren
  • Legen Sie danach eine Datei TwPdfRechnung.php im Verzeichnis twpdf an und kopieren den Inhalt folgender Datei dort hinein. TwPdfRechnung.php kopieren
  • Öffnen Sie die soeben erstellte Datei rechnung.php in Ihrem Browser. Dieser sollte dann schon die generierte PDF-Datei anzeigen (wie in dieser Demo ).

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Beschreibung der Datei 'rechnung.php'

Als erstes werden dort die "Zutaten" eingebunden, das sind in diesem Falle die FPDF-Klasse und die Klasse TwPdfRechnung.

// FPDF-Zeugs und die spezielle TwPdf-Klasse includen
define("FPDF_FONTPATH","fpdf16/font/");
include_once('fpdf16/fpdf.php');
include_once("twpdf/TwPdfRechnung.php");

Danach schreiben wir alles in Variablen, was später auf der Rechnung auftauchen soll. Dies könnten Sie natürlich auch alles in einem Formular abfragen, hier wird dies jedoch fest in den Code geschrieben, um die Komplexität dieses Artikels nicht unnötigerweise aufzublähen.

Wichtig ist dann eigentlich nur, diese Variablen in eine PHP-Session zu schreiben

// alles in die Session rein
$_SESSION['twArrRechnungsdaten']      = $arrDat;
$_SESSION['twArrRechnungspositionen'] = $arrPos;

und die Klasse TwPdfRechnung aufzurufen.

// pdf erzeugen
$twpdf = new TwPdfRechnung(); 

// pdf ausgeben (im Browser oder in Datei schreiben)
$twpdf->Output();   // Ausgabe (wenn in Datei schreiben, dateiname in Klammer)

Wenn man bei Output() einen Dateiname mit angibt (beispielsweise: Output("meinedatei.pdf");), dann wird das erzeugte PDF in eine Datei mit dem angegebenen Name geschrieben.
Wir möchten jedoch die PDF-Datei nur im Browser anzeigen und schreiben deshalb Output();.

Wichtig in diesem Zusammenhang ist noch, dass in dieser Datei VOR dem öffnenden <?php und NACH dem schließenden ?> kein einziges Zeichen mehr steht, auch kein Leerzeichen, Zeilenumbruch oder Sonstiges.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Beschreibung der Datei 'TwPdfRechnung.php'

Der Code dieser Datei sieht auf dem ersten Blick für Sie eventuell erst einmal sehr kompliziert aus. Aber das ist wie mit jeder neuen Sache, hat man es erstmal begriffen, dann ist es auf einmal ganz einfach.

Also lassen Sie sich bitte nicht von dem vielen Code abschrecken, ein Großteil davon ist jetzt erstmal gar nicht so wichtig. Ganz grob gesagt sind für Sie zu Beginn diese 4 Funktionen interessant:

__construct()
wird beim Erzeugen eines Objektes dieser Klasse automatisch aufgerufen, lädt die PHP-Session-Variablen, erledigt alle für die PDF-Erzeugung relevanten Dinge
Header()
erstellt die Kopfzeile, wird automatisch aufgerufen, in unserem Falle wird hier auch gleich das Layout der gesamten Seite festgelegt
Footer()
erstellt die Fußzeile, wird automatisch aufgerufen
twShowRechnungspositionen()
stellt die einzelnen Positionen der Rechnung in einer Art Tabelle dar, muss extra aufgerufen werden

Nun diese Datei nochmal im Einzelnen. Am Anfang werden wieder die für diese Klasse relevanten Variablen (-Arrays) deklariert.

  // Variablen und Arrays
  private $twArrRechnungsdaten      = array();
  private $twArrRechnungspositionen = array();
  private $twArrSpaltenbreiten      = array();
  private $twArrSpaltenkoepfe       = array();

die Funktion __construct()

Das Seitenformat, die Maßeinheit und die Seitengröße festlegen.

    // Konstruktor der vererbenden Klasse (FPDF) aufrufen
    parent::__construct('P', 'mm', 'A4'); // L=Querformat(Landscape), P=Hochformat(Portrait)

Unsere in der Datei rechnung.php festgelegten Inhalte der Rechnung aus der PHP-Session laden.

    // Session-Variablen aus dem aufrufenden Skript übernehmen
    $this->twArrRechnungsdaten      = $_SESSION['twArrRechnungsdaten'];
    $this->twArrRechnungspositionen = $_SESSION['twArrRechnungspositionen'];		

Noch ein paar grundlegende Anweisungen, wie groß die Seite im Browser angezeigt werden soll, wann ein Seitenumbruch erfolgen soll und (nicht so wichtig) die Gesamtanzahl der Seiten ermitteln.

    // Einstellungen für das PDF
    $this->SetDisplayMode( 100 );         // wie groß wird Seite angezeigt(in %)
    $this->SetAutoPageBreak(true, 50);    // 50mm von unten erfolgt ein Seitenumbruch
    $this->AliasNbPages();                // Anzahl der Seiten berechnen ({nb}-sache)	

Die eigentliche Erzeugung des PDF

    // Seite erzeugen
    $this->AddPage();                     // PDF starten (ruft auch Header() und Footer() auf

Und noch zwei Dinge, speziell für unsere PDF-Rechnung. Aufruf unserer Funktion zur Erstellung der Tabelle mit den Rechnungspositionen und einer speziellen Funktion, die unsere Zahlungsbedingungen und den Gesamtbetrag der Rechnung bei mehrseitigen Rechnungen nur auf der letzten Seite anzeigt.

    // zusätzliche Sachen
    $this->twShowRechnungspositionen();   // Tabelle mit allen Rechnungspositionen
    $this->twShowLetzteSeite();           // nur auf der letzten Seite

die Funktion Header()

Hier geht es nun endlich an das eigentliche "Designen" des Aussehens der Rechnung. Um die einzelnen Anweisungen besser zu verstehen, können sie die Beschreibungen in der offiziellen FPDF-Dokumentation nachlesen. Dort wird in kurzen, verständlichen Sätzen erklärt, worum es bei jeder Anweisung geht. Die Doku kann von dort auch (natürlich als PDF-Datei) heruntergeladen werden.

Die Funktion Header() ist grob in drei Bereiche unterteilt (gilt für mehrseitige Rechnungen):

  • Bereiche, die auf jeder Seite angezeigt werden
  • Bereiche, die nur auf der ersten Seite angezeigt werden
  • Bereiche, die auf allen Seiten, außer auf der Ersten angezeigt werden

Meist kommen in dieser Funktion immer wieder dieselben Anweisungen vor. Das ist das Wesen von FPDF, von oben herunter jedes einzelne Element immer wieder neu erstellen. Der Quellcode in dieser Funktion ist einigermaßen kommentiert, sodass sich vielleicht einige Dinge von selbst erklären. Die wichtigsten Anweisungen sind wohl:

  • SetFont legt die Schriftart fest
  • SetTextColor legt die Textfarbe fest
  • SetFillColor legt die Füllfarbe fest (Hintergrund)
  • SetDrawColor legt die Rahmenfarbe fest
  • SetLineWidth legt die Rahmenstärke fest
  • twRundeckbereich legt die Rundung der Boxen fest (eigene Funktion)
  • SetXY legt Position fest (meist die Startposition einer folgenden Anweisung)
  • Cell zeichnet eine Art Zelle, meist mit enthaltenem Text (mit oder ohne Rahmen und Hintergrund)
  • Image fügt ein Bild ein

Als Bild können Sie Ihr Logo hier einfügen. Zum Testen können Sie auch erstmal dieses Beispielbild verwenden. Screenshot
Speichern Sie das Bild im Verzeichnis 'twPdf', oder passen Sie im Quellcode den Pfad zu Ihrem Logo an.

die Funktion Footer()

Für diese Funktion gilt PDF-mäßig dasselbe wie für die vorherige Header(), nur dass hier halt die Fußzeile erstellt wird.

die Funktion twShowRechnungspositionen()

Das ist die etwas komplizierte Funktion. Sie ist nicht direkt bei FPDF enthalten, sondern selbst programmiert. Hier wird eine Art Tabelle für die einzelnen Rechnungspositionen erzeugt.

Wir geben zuerst die Spaltenbreiten (in mm) und die Beschriftungen der Spaltenköpfe an.

    // Spaltenbreiten und Beschriftung der Spaltenköpfe festlegen
    $this->twSetSpaltenbreiten(array(8, 99, 14, 20, 20));
    $this->twSetSpaltenkoepfe(array('Pos', 'Text', 'Menge', 'Preis', 'Gesamt'));

Nach ein paar Formatanweisungen erzeugt folgender Code die Spaltenköpfe.

    for ($i=0; $i<count($this->twArrSpaltenkoepfe); $i++) {
      $this->Cell($this->twArrSpaltenbreiten[$i], 7, $this->twArrSpaltenkoepfe[$i], 1, 0, 'C', 1); 
    }
    $this->ln();

Die einzelnen Zeilen für die Rechnungspositionen werden folgendermaßen erstellt. Die darin für jede Zeile aufgerufene Funktion twShowZeileMitMultiCell ist wieder eine selbst programmierte Funktion.

    foreach ($this->twArrRechnungspositionen as $pos) {
      $i++;
      $this->twShowZeileMitMultiCell(array(
              $i,
              $pos['text'],
              sprintf("%9.2f", $pos['menge']),
              sprintf("%9.2f", $pos['einzelpreis']),
              sprintf("%9.2f", $pos['gesamtpreis'])
              ));
      $this->SetX(27);  // sonst gehts immer ganz links los...
    }
    $this->Cell(array_sum($this->twArrSpaltenbreiten), 0, '', 'T');  //Tabellenlinie unten

sonstige (eigene) Funktionen

In dieser Klasse sind noch weitere Funktionen programmiert, auf die hier nicht näher eingegangen werden soll, um den Umfang dieses Artikels nicht zu sprengen.

Es handelt sich dabei um die Funktion twShowLetzteSeite(), sowie um den Quellcode zwischen

  /* twTabelleMitMultiCell START -------------------------------------------- */
  ...
  ...
  /* twTabelleMitMultiCell END ---------------------------------------------- */

und

  /* twRundeckbereich START ------------------------------------------------- */
  ...
  ...
  /* twRundeckbereich END --------------------------------------------------- */

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Schlussbemerkungen

Dieses Rechnungs-Beispiel ist sicher noch recht ausbaufähig, stellt aber mit der Klasse TwPdfRechnung eine solide Vorlage dar. Anhand dieser Klasse kann man nach einer gewissen Einarbeitungszeit seine an den eigenen Geschmack angepasste PDF-Rechnung selbst zurechtzimmern. Der Quellcode dieses Beispiels darf frei verwendet werden.

Die Anregungen und das Grundverständnis vor Allem für die Tabelle mit MultiCell und den abgerundeten Ecken habe ich aus den Add-On's von FPDF bezogen.

Für alle, denen es nicht schnell genug gehen kann, gibts hier auch den gesamten Quellcode als zip-Datei.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  Bei Fragen, Anregungen oder dergleichen schreiben Sie doch einen Kommentar in das Blog