Zum Inhalt springen
vanheek.biz
Startseite Praxistests Web & Tools Alltag
Kontakt

Praxistest · Stand: 31. August 2026

TCPDF: PDFs aus PHP — das Gratis-Arbeitstier hinter vier meiner Projekte

Wer eine Webanwendung baut, steht früher oder später vor demselben Wunsch: „Kann ich das als PDF haben?“ — die Zählliste, der Beleg, die Monatsauswertung. Meine Antwort darauf heißt seit Jahren TCPDF: eine kostenlose PHP-Bibliothek (LGPL), die ohne Server-Erweiterungen auskommt und deshalb auf jedem gewöhnlichen Shared Hosting läuft. Bei mir arbeitet sie in vier Projekten: Die Inventur-App druckt damit ihre Zähllisten, die Testkauf-Erfassung ihre Belege, der Haushaltsplaner seine Auswertungen, und ein viertes Werkzeug nutzt sie für Formulare. Grund genug für einen ausführlichen Blick — mit lauffähigem Code und den echten Ergebnissen.

Warum ausgerechnet TCPDF?

Die Bibliothek gibt es seit 2002, sie stammt von Nicola Asuni und ist laut Packagist über 115 Millionen Mal installiert worden — ein Urgestein, auf dem halb PHP-Land aufbaut. Für Hobby-Projekte zählen drei Dinge: Sie kostet nichts, sie braucht nur PHP (kein ImageMagick, kein Systemwerkzeug), und sie hat Barcodes eingebaut — EAN, Code 128, QR-Codes, direkt aus der Kiste. Installation wahlweise per composer require tecnickcom/tcpdf oder — so mache ich es auf Shared Hosting — als entpackter Ordner, der per require eingebunden wird.

Beispiel 1: Vom leeren Blatt zum Brief

Das Grundprinzip: Man erzeugt ein Dokument, wählt Schrift und Ränder und schreibt hinein — gedanklich wie auf ein Blatt Papier, mit Maßen in Millimetern:

<?php
require __DIR__ . '/tcpdf/tcpdf.php';

$pdf = new TCPDF('P', 'mm', 'A4');   // Hochformat, Millimeter, A4
$pdf->setPrintHeader(false);          // Standard-Kopf-/Fußzeile aus
$pdf->setPrintFooter(false);
$pdf->SetMargins(25, 25, 20);
$pdf->AddPage();

$pdf->SetFont('helvetica', '', 11);
$pdf->Write(0, "Musterstadt, den 30.08.2026\n\n");

$pdf->SetFont('helvetica', 'B', 14);
$pdf->Write(0, "Betreff: PDF aus vier Zeilen Code\n\n");

$pdf->SetFont('helvetica', '', 11);
$pdf->MultiCell(0, 0,
    "Sehr geehrte Leserin, sehr geehrter Leser,\n\n" .
    "dieses Dokument entstand ohne Word, ohne Drucker-Dialog und ohne " .
    "Cloud-Dienst — nur mit PHP und der kostenlosen Bibliothek TCPDF. " .
    "Umlaute wie Ä, Ö, Ü und das ß funktionieren dabei einfach.\n\n" .
    "Mit freundlichen Grüßen\nIhr Skript",
    0, 'L');

$pdf->Output(__DIR__ . '/brief.pdf', 'F');   // 'F' = als Datei speichern
Mit TCPDF erzeugter Brief: Datum, fette Betreffzeile und Fließtext mit deutschen Umlauten
Das Ergebnis, unverändert aus dem Skript — inklusive Umlauten und ß.

Der letzte Parameter von Output() ist eine der nützlichsten Stellschrauben: 'I' zeigt das PDF im Browser, 'D' erzwingt den Download, 'F' speichert serverseitig in eine Datei — Letzteres nutze ich für nächtlich erzeugte Berichte.

Beispiel 2: Die Zählliste — Tabellen aus Zellen

Das Arbeitstier jeder Fachanwendung ist die Tabelle. TCPDF kann zwar eingeschränkt HTML rendern, aber für sauberes Layout fahre ich nach Jahren Erfahrung besser mit Cell() — hier der Tabellen-Kern, aufbauend auf dem Grundgerüst aus Beispiel 1: Jede Zelle bekommt Breite, Höhe, Rahmen und Ausrichtung — wie Lego, nur in Millimetern:

$artikel = [   // je Zeile: [EAN, Artikeltext, Menge, MHD]
    ['4000140714658', 'Orangina Zero mit Fruchtfleisch', 25, '—'],
    ['5075331932004', 'Lambrusco',                        5, '21.03.2026'],
    // …
];
$breiten = [35, 95, 20, 30];

// Kopfzeile mit Hintergrund
$pdf->SetFillColor(240, 240, 240);
$pdf->SetFont('helvetica', 'B', 10);
foreach (['EAN', 'Artikel', 'Menge', 'MHD'] as $i => $titel) {
    $pdf->Cell($breiten[$i], 8, $titel, 1, 0, 'L', true);
}
$pdf->Ln();

// Zeilen mit Wechselschattierung, Summe nebenbei
$pdf->SetFont('helvetica', '', 10);
$summe = 0;
foreach ($artikel as $nr => [$ean, $name, $menge, $mhd]) {
    $fuellen = $nr % 2 === 1;
    $pdf->SetFillColor(250, 250, 250);
    $pdf->Cell($breiten[0], 7, $ean,   1, 0, 'L', $fuellen);
    $pdf->Cell($breiten[1], 7, $name,  1, 0, 'L', $fuellen);
    $pdf->Cell($breiten[2], 7, $menge, 1, 0, 'R', $fuellen);
    $pdf->Cell($breiten[3], 7, $mhd,   1, 1, 'L', $fuellen);
    $summe += $menge;
}

// Summenzeile
$pdf->SetFont('helvetica', 'B', 10);
$pdf->Cell($breiten[0] + $breiten[1], 8, 'Summe', 1);
$pdf->Cell($breiten[2], 8, $summe, 1, 0, 'R');
$pdf->Cell($breiten[3], 8, '', 1, 1);
Mit TCPDF erzeugte Zählliste: Tabelle mit EAN, Artikel, Menge und MHD, Wechselschattierung und Summenzeile
Vier Datenzeilen, Kopf, Schattierung, Summenzeile — exakt so druckt meine Inventur-App ihre Listen.

Die Denkweise, an die man sich gewöhnen muss: Der fünfte Parameter von Cell() steuert, ob der Cursor danach rechts weiterläuft (0) oder eine neue Zeile beginnt (1). Wer das einmal verinnerlicht hat, baut Tabellen schneller als in jeder Textverarbeitung.

Beispiel 3: Der Trumpf — Barcodes ohne Zusatzbibliothek

Hier schlägt TCPDF alles, was ich sonst probiert habe: Ein EAN-Strichcode und ein QR-Code sind je ein einziger Methodenaufruf. Für ein Regal-Etikett im eigenen Format reicht das hier:

$pdf = new TCPDF('L', 'mm', [60, 100]);   // eigenes Etikettenmaß
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->SetMargins(6, 6, 6);
$pdf->SetAutoPageBreak(false);             // wichtig bei Etiketten!
$pdf->AddPage();

$pdf->SetFont('helvetica', 'B', 13);
$pdf->Cell(0, 7, 'Orangina Zero 1,0 l', 0, 1);
$pdf->SetFont('helvetica', '', 22);
$pdf->Cell(0, 11, '1,49 €', 0, 1);

// 1D: EAN-13 mit Klartextzeile darunter
$pdf->write1DBarcode('4000140714658', 'EAN13', 6, 32, 55, 18, 0.4,
    ['text' => true, 'font' => 'helvetica', 'fontsize' => 8]);

// 2D: QR-Code, z. B. zum Artikel im eigenen System
$pdf->write2DBarcode('https://inventur.vanheek.biz/', 'QRCODE,M', 70, 26, 24, 24);
Mit TCPDF erzeugtes Regal-Etikett: Artikelname, Preis, EAN-13-Strichcode und QR-Code
Ein komplettes Regal-Etikett aus ~15 Zeilen PHP — der Strichcode ist scanbar.

Ehrliche Praxistipps aus vier Projekten

Schriften mit Bedacht wählen. Die Kern-Schriften (helvetica, times, courier) halten PDFs klein. Volle Unicode-Schriften wie dejavusans können Sonderzeichen aller Sprachen — blähen die Dateien aber deutlich auf. Für deutsche Geschäftsdokumente reicht helvetica fast immer.

writeHTML ist eine Abkürzung, kein Browser. TCPDF versteht nur eine Teilmenge von HTML und CSS. Für schnelle Textblöcke gut, für pixelgenaue Tabellen wird es zäh — dann lieber Cells, siehe oben.

Die API zeigt ihr Alter. Hunderte Methoden, gemischte Namenskonventionen, eine Dokumentation, die hauptsächlich aus Beispieldateien besteht. Mein Rat: die offiziellen Beispiele als Steinbruch benutzen — irgendwo dort wurde fast alles schon einmal vorgemacht.

AutoPageBreak kennt keine Gnade. Bei Etiketten und festen Formaten immer SetAutoPageBreak(false) setzen, sonst rutscht der QR-Code auf eine mysteriöse zweite Seite.

Klassiker und Nachfolger

Volle Transparenz zum Projektstatus (Stand 31.08.2026): Das klassische TCPDF ist offiziell im Wartungsmodus — gepflegt wird es trotzdem erstaunlich aktiv, die Versionen 7.0.7 und 6.11.4 erschienen erst vor wenigen Tagen; aktuelle Zweige verlangen PHP 8.2 oder neuer. Die aktive Weiterentwicklung steckt im modularen Nachfolger tc-lib-pdf, den der Autor für neue Projekte empfiehlt — mit vollem UTF-8 samt Rechts-nach-links-Schriften, SVG, digitalen Signaturen und PDF/A. Wichtig zu wissen: Er ist ausdrücklich kein Drop-in-Ersatz, verlangt Composer und eine eigene Font-Generierung. Meine Einordnung: Bestehende Projekte auf dem Klassiker weiterlaufen lassen und aktuell halten; wer heute neu anfängt und mit Composer arbeitet, schaut sich zuerst den Nachfolger an. Und wer die Bibliothek jahrelang gratis einsetzt, darf dem Autor gern eine Spende dalassen — zwei Jahrzehnte Pflege sind kein Selbstläufer.

Fazit

TCPDF ist kein glamouröses Werkzeug — es ist das zuverlässige. Null Euro, null Serveranforderungen, Barcodes inklusive, und nach zwei Jahrzehnten immer noch gepflegt. Alle drei Beispiele wurden für diesen Artikel tatsächlich ausgeführt, und die Bilder sind ungeschönte Renderings genau dieser PDFs (Beispiel 2 zeigt den Tabellen-Kern auf dem Grundgerüst aus Beispiel 1). Wenn deine Webanwendung das nächste Mal gefragt wird, ob es das „auch als PDF“ gibt, lautet die Antwort: ja — mit ein paar Dutzend Zeilen PHP.

© 2026 Matthias van Heek Impressum · Datenschutzerklärung