FPDF-Tutorial - Rechnungs-Posten und mehrspaltiger Text

FPDF-Tutorial - Rechnungs-Posten und mehrspaltiger Text
Von Lars Ebert am 26.08.13, 11:00
Kategorien: PHP, Programmieren and Tutorials

Im letzten Artikel dieser Serie hast Du gelernt, Blocksatz in FPDF zu generieren. Was uns jetzt für eine Rechnung noch fehlt, sind die Rechnungs-Posten. Diese wollen wir nun in zwei Spalten darstellen. Links wird der Artikel oder das Produkt aufgelistet und rechts der Preis. So können wir am Ende die Summe der Rechnung übersichtlich darstellen.

Jetzt aber los!

Artikelserie: FPDF-Tutorial - PDF-Generierung mit PHP

Dieser Artikel ist Teil einer mehrteiligen Artikelserie. Lies dir auch die restlichen Teile durch!

  1. FPDF-Tutorial: Ein PDF erstellen und Text ausgeben
  2. FPDF-Tutorial: Blocksatz und Fließtext
  3. FPDF-Tutorial - Rechnungs-Posten und mehrspaltiger Text

Schritt 10: Eine neue Methode für Rechnungs-Posten

Auch für die Posten werden wir eine neue Methode in unserer Invoice-Klasse bereistellen. So können wir später einfach die Posten in beliebiger Reihenfolge ausgeben und auch zwischendurch Text-Absätze einschieben. Um das zu testen, ergänze die Generierung des PDFs folgendermaßen:

<?php
	
	$items = array(
		array(
			'name' => 'Produkt 1',
			'description' => 'Lorem ipsum ad qui amet dolore, vitae cetero quaerendum mel ea. Facilis fastidii duo no.',
			'unitprice' => 5.2,
			'quantity' => 3
		),
		array(
			'name' => 'Produkt 2',
			'description' => 'Lorem ipsum ad qui amet dolore, vitae cetero quaerendum mel ea. Facilis fastidii duo no.',
			'unitprice' => 1,
			'quantity' => 9
		),
		array(
			'name' => 'Produkt 3',
			'description' => 'Lorem ipsum ad qui amet dolore, vitae cetero quaerendum mel ea. Facilis fastidii duo no.',
			'unitprice' => .99,
			'quantity' => 18
		)
	);
	
	$invoiceNumber = date('Ymd') . '-' . rand(0, 100);
	$date = new DateTime();
	
	require_once('invoice.php');
	
	$invoice = new Invoice($invoiceNumber, $date);
	
	$invoice->Paragraph('Sehr geehrte Frau Mustermann,

vielen Dank für Ihren Einkauf bei Advitum.de. Dies ist Ihre Rechnung!

Lorem ipsum ad qui amet dolore, vitae cetero quaerendum mel ea. Facilis fastidii duo no. Viris partiendo ius no, alia animal nam at. Feugait imperdiet ius an, no quis facer lucilius vis. Aliquam saperet contentiones ex pro, id idque offendit ius. Fugit suavitate ad eam, ut essent debitis cum.');
	
	$invoice->Item(array_shift($items));
	
	$invoice->Paragraph('Lorem ipsum ad qui amet dolore, vitae cetero quaerendum mel ea. Facilis fastidii duo no. Viris partiendo ius no, alia animal nam at. Feugait imperdiet ius an, no quis facer lucilius vis. Aliquam saperet contentiones ex pro, id idque offendit ius. Fugit suavitate ad eam, ut essent debitis cum.');
	
	foreach($items as $item) {
		$invoice->Item($item);
	}
	
	$invoice->output();
	
?>

Die Methode Item wird später einen Rechnungs-Posten entgegennehmen und diesen Darstellen. Nach dem ersten Posten schieben wir hier einen Text-Absatz ein.

Nun müssen wir diese neue Methode auch in der Klasse bereitstellen.

public function Item($item) {
	$this->ln($this->rythm);
	
	$this->SetFont('Helvetica', 'B', 9);
	$this->Cell($this->leftColumnWidth + $this->gutter, 0, $item['name']);
	
	$this->SetFont('Helvetica', '', 7);
	$this->FitCell($item['quantity'] . ' á EUR ');
	$this->Currency($item['unitprice']);
	
	$this->ln($this->rythm);
	
	$this->SetX($this->rightColumnX);
	$this->FitCell('EUR ');
	
	$this->SetFont('Helvetica', 'B', 12);
	$this->Currency($item['quantity'] * $item['unitprice']);
	
	$this->sum += $item['quantity'] * $item['unitprice'];
	
	$this->SetX($this->leftMargin);
	$this->SetFont('Helvetica', '', 9);
	$this->BlockCell($item['description'], $this->leftColumnWidth);
	
	$this->ln($this->rythm * 3);
}

Zunächst sorgen wir für einen Zeilenumbruch mit der Methode ln. Nun können wir den eigentlichen Posten ausgeben. In der linken Spalte geben wir zunächst fettgedruckt den Namen des Postens an. Die breite der Zelle wählen wir hier mit $this->leftColumnWidth + $this->gutter genau so, dass sie am linken Rand der rechten Spalte endet. So können wir nun direkt die erste Zeile der rechten Spalte ausgeben.

Hierzu gibt es zwei neue Methoden, die wir gleich noch erstellen müssen. Die Methode FitCell gibt den übergebenen Text in einer neuen Zelle aus, die genau so breit ist wie der Text. Die Methode Currency ist für die Darstellung des Betrags zuständig. Das lagere ich deshalb aus, da wir noch öfter auf der Rechnung beträge ausgeben müssen. So werden diese immer einheitlich dargestellt und wir müssen uns nicht wiederholen.

Nun aber weiter im Text. Als nächstes erzwingen wir wieder einen Zeilenbruch und springen dann wieder zur rechten Spalte (Zeile 13). Hier geben wir nun den Betrag des Postens aus, der sich aus dem Einzelpreis und der Stückzahl errechnet. Diesen Betrag addieren wir auch direkt zur Gesamtsumme der Rechnung, welche in $this->sum gespeichert ist.

Als letztes springen wir wieder in die linke Spalte und geben hier mittels BlockCell die Artikel-Beschreibung aus (Zeile 23). Am Ende generieren wir noch einen Zeilenumbruch.

Nun erstellen wir die beiden Methoden FitCell und Currency

private function FitCell($text) {
	$width = $this->GetStringWidth($text);
	$this->Cell($width, 0, $text);
}

private function Currency($amount) {
	$euro = floor($amount);
	$cent = round(($amount - $euro) * 100);
	
	if($cent < 10) {
		$cent = '0' . $cent;
	}
	
	$this->FitCell($euro . ',' . $cent);
}

Die Methode FitCell ermittelt zunöchst mit der Methode GetStringWidth die Breite des darzustellenden Strings. Anschließend wird dieser Text in einer Zelle mit genau dieser Breite dargestellt.

In der Methode Currency ermitteln wir zunächst die Euro- und Cent-Beträge, wobei wir hier auf den ganzen Cent runden. Anschließend sorgen wir dafür, dass der Centbetrag auf jeden Fall zweistellig ist, indem wir gegebenenfalls eine führende Null hinzufügen. Abschließend wird der Betrag mit der Methode FitCell ausgegeben.

Schauen wir uns die Rechnung nun erneut an, sehen wir die Darstellung der Posten. Hat alles Funktioniert? Wunderbar, dann schließen wir die Rechnung jetzt mit der Summe und einer Signatur ab!

Schritt 11 - Ende der Rechnung mit Footer

Erinnerst Du Dich noch an die Methode Header? Diese Methode wird von FPDF am Anfang jeder neuen Seite aufgerufen. Im ersten Teil dieser Serie haben wir diese dazu genutzt, um die Rechnungs-Nummer, das Datum etc. auf die Rechnung zu bringen. Nun werden wir das Äquivalent der Header-Methode für den Seiten-Abschluss, die Methode Footer, dazu nutzen, die Rechnung abzuschließen.

Dazu brauchen wir in der index.php nichts ändern, denn die Methode Footer wird von FPDF auch automatisch aufgerufen. Wir müssen diese jetzt lediglich in unserer Invoice-Klasse bereitstellen.

public function Footer() {
	$this->SetLineWidth(.2);
	$this->Line($this->rightColumnX, $this->GetY(), $this->rightColumnX + 25, $this->GetY());
	
	$this->ln($this->rythm);
	$this->SetX($this->rightColumnX);
	
	$this->SetFont('Helvetica', '', 7);
	$this->FitCell('EUR ');
	
	$this->SetFont('Helvetica', 'B', 12);
	$this->Currency($this->sum);
	
	$this->ln($this->rythm);
	$this->SetX($this->rightColumnX);
	$this->SetFont('Helvetica', '', 7);
	$this->Cell(0, 0, 'Gesamtsumme');
	
	$this->ln($this->rythm);
	$this->SetFont('Helvetica', '', 9);
	
	$this->Paragraph('Wir wünschen Ihnen viel Spaß mit dem Produkt XYZ.


Mit freundlichen Grüßen,

Ihr Lars Ebert von Advitum.de');
}

Als erstes Zeichen wir eine horizontale Linie in die rechte Spalte, als Summen-Strich. Dazu setzen wir die Linien-Breite in Zeile 2 auf 0,2 Millimeter. Mit der Methode Line erstellen wir die Linie selbst.

Anschließend f+gen wir einen Zeilenumbruch ein, springen in die rechte Spalte und geben hier die Gesamtsumme der Rechnung aus. Hier können wir wieder auf unsere Methode Currency zurückgreifen. Unter der Summe schreiben wir noch »Gesamtsumme« und springen anschließend wieder in die linke Spalte.

Nun geben wir mit der Methode Paragraph noch abschließende Worte und eine Signatur ein.

Schauen wir uns wieder die Rechnung im Frontend an, sehen wir direkt das Resultat. Am Ende wir nun die Rechnungs-Summe ausgegeben.

Ausblick: Wie geht es weiter?

Deine Rechnung ist nun fertig. Allerdings sind wir noch nicht am Ende dieser Artikelserie angekommen. Nun, wo Du Dich mit den grundlegenden Funktionen von FPDF vertraut gemacht hast, werden wir uns mit einigen Aspekten detaillierter beschäftigen. Denn die Flexibilität von FPDF hat den Preis, dass man viele Funktionen selbst erstellen muss, wie zum Beispiel den Blocksatz.

Einige Punkte, die wir in Zukunft genauer beleuchten werden, sind die Formatierung von Text mit Blocksatz, Hoch- und Tiefstellung usw. Hier werde ich jeweils im Detail darauf eingehen, wie Du alles sehr kleinschrittig anpassen kannst.

Zum Abschluss habe ich eine Frage an Dich: Welche Funktionen würdest Du gerne genauer behandeln? Schreib mir einfach einen Kommentar!