TCPDF-Ganzseitentabelle

11

Ich habe viele Möglichkeiten ausprobiert, um die Tabelle an die Seite (A4) anzupassen, wie auf dem Bild gezeigt: Geben Sie hier die Bildbeschreibung ein Ich habe viel gesucht, aber im Web nichts Nützliches gefunden. Ich verwende eine dynamische Tabelle, bis auf die Breite der Tabelle ist alles in Ordnung. Hier ist mein Code:

$content = '<table><thead><tr><th class="bg-dark text-white" align="center">#</th><th align="center" class="bg-dark text-white">Code</th><th align="left" class="bg-dark text-white">Description</th><th align="center" class="bg-dark text-white">Item Type</th></tr></thead><tbody><tr style="background-color: #f2f2f2;"><td align="center">1</td><td align="center">1001</td><td align="left">Pofak</td><td align="center">Fixed Price</td></tr><tr ><td align="center">2</td><td align="center">1002</td><td align="left">Ice</td><td align="center">Weight</td></tr><tr style="background-color: #f2f2f2;"><td align="center">3</td><td align="center">1003</td><td align="left">Minoo</td><td align="center">Fixed Price</td></tr><tr ><td align="center">4</td><td align="center">1004</td><td align="left">Bastani</td><td align="center">Fixed Price</td></tr><tr style="background-color: #f2f2f2;"><td align="center">5</td><td align="center">1005</td><td align="left">Chocolate</td><td align="center">Weight</td></tr><tr ><td align="center">6</td><td align="center">1006</td><td align="left">Brush</td><td align="center">Fixed Price</td></tr><tr style="background-color: #f2f2f2;"><td align="center">7</td><td align="center">1007</td><td align="left">Apple</td><td align="center">Weight</td></tr><tr ><td align="center">8</td><td align="center">1008</td><td align="left">Water</td><td align="center">Fixed Price</td></tr><tr style="background-color: #f2f2f2;"><td align="center">9</td><td align="center">1009</td><td align="left">Cleaner</td><td align="center">Fixed Price</td></tr><tr ><td align="center">10</td><td align="center">1001</td><td align="left">Pofak</td><td align="center">Fixed Price</td></tr><tr style="background-color: #f2f2f2;"><td align="center">11</td><td align="center">1002</td><td align="left">Ice</td><td align="center">Weight</td></tr><tr ><td align="center">12</td><td align="center">1003</td><td align="left">Minoo</td><td align="center">Fixed Price</td></tr><tr style="background-color: #f2f2f2;"><td align="center">13</td><td align="center">1004</td><td align="left">Bastani</td><td align="center">Fixed Price</td></tr><tr ><td align="center">14</td><td align="center">1005</td><td align="left">Chocolate</td><td align="center">Weight</td></tr><tr style="background-color: #f2f2f2;"><td align="center">15</td><td align="center">1006</td><td align="left">Brush</td><td align="center">Fixed Price</td></tr></tbody></table>';
$newContent = '
    <style type="text/css">
    table{width:100%;}
    table, table td, table th{
        border-collapse: collapse;
        border: solid 1px #ababab;
    }
    .text-dark, table td{
        color: #343a40;
    }
    .text-white{
        color: #ffffff;
    }
    table td,
    table th {
        font-size: 11px;
        padding: 3px;
        line-height: 1.2;
        font-family:arial;
    }

    .bg-dark {
        background-color: #343a40;
    }
    .bg-secondary {
        background-color: #6c757d;
    }
    .bg-white {
        background-color: #ffffff;
    }
    .text-left {
        text-align: left;
    }
    .text-right {
        text-align: right;
    }
    .text-center {
        text-align: center;
    }
    </style>
    ';
    $newContent .= '<page>'.$content.'</page>';

    try {
        $html2pdf = new Html2Pdf('P', 'A4', 'en', true, 'UTF-8', 5);
        $html2pdf->pdf->SetDisplayMode('real');
        $html2pdf->writeHTML($newContent);
        $PDFName = "ItemLists_".date('Y.m.d_H.i.s').".pdf";
        $html2pdf->output($PDFName, 'I');
    } catch (Html2PdfException $x) {
        $html2pdf->clean();

        $formatter = new ExceptionFormatter($x);
        echo $formatter->getHtmlMessage();
    }

Danke vielmals

Mohsen Newtoa
quelle
Dies ist tatsächlich ein Fehler in der Html2PDF-Bibliothek. Prüfung einer möglichen Problemumgehung.
EPB
Es ist übrigens erwähnenswert, dass Html2PDF einen eigenen HTML-Parser verwendet. style="width: 100%"speichert die korrekt konvertierte Breite in MM (obwohl das width-Attribut dies nicht tut!). Html2PDF scheint sie jedoch beim Rendern von Tabellen nicht tatsächlich zu verwenden.
EPB

Antworten:

4

Html2PDF verwendet nicht das HTML-Parser / Render-System von TCPDF. Es implementiert seine eigenen und die Implementierung vergrößert die Spalten nicht automatisch, um 100% des Speicherplatzes auszufüllen.

Daher müssen Sie in Html2PDF nicht nur 100% Breite für die Tabelle festlegen, sondern auch prozentuale Breiten für jede der Zellen festlegen. (Und aufgrund eines merkwürdigen Verhaltens mit dem widthAttribut in Html2PDF verwenden Sie CSS, um die Breiten festzulegen.)

TCPDFs native writeHTMLsetzt jede Spalte auf die gleiche Breite, sofern keine anderen Spezifikationen vorliegen . (In einer 4-Spalten-Tabelle sind beispielsweise alle Zellen zu 25% vorhanden.) Das von Ihnen verwendete CSS wird jedoch nicht unterstützt, sodass für das Markup einige Anpassungen erforderlich sind, um diesen Weg zu gehen.

Um dieses grundlegende Verhalten in Html2PDF nachzuahmen, können Sie Ihren Zellen einfach explizit äquivalente Breiten hinzufügen. Fügen Sie beispielsweise Ihren table td, table thStilregeln eine Breitenspezifikation hinzu .

Hier ist ein Beispiel mit den folgenden CSS-Regeln für eine vierspaltige Tabelle:

table { width: 100%; }
table th, table td { width: 25%; }

Natürlich sieht es am besten aus, wenn Sie Breiten angeben, die zu Ihrem Inhalt passen.

Beispiel mit äquivalenten Spalten


AKTUALISIEREN

Ich werde einen Teil der Diskussion über TCPDF weiter unten verlassen, da dies etwas zur Schaffung einer potenziell nützlichen Klasse für führt Html2pdf. TCPDF bietet einige nützliche Methoden zum Messen der Länge eines Strings. Wenn Sie die Größe der Zeichenfolgen in den Spalten messen, können Sie Ihre eigene automatische Spaltengröße erstellen.

Ich habe eine Proof-of-Concept-Klasse für Github unter https://github.com/b65sol/random-classes erstellt

Zuerst verwenden wir die Klasse, um die Konstruktion des HTML zu vermitteln. Auf diese Weise werden die Spaltenklassen zum Festlegen der Breiten hinzugefügt, und wir müssen HTML nicht analysieren, um den gemessenen Inhalt zu extrahieren.

Dann müssen wir eine Strategie für die Auswahl unserer Spaltenbreiten auswählen. In der folgenden Demo werden beispielsweise die Spalten gemessen und die prozentualen Mindestbreiten für jede Spalte basierend auf dem längsten Wort ermittelt. (Vermeidet Wortbrüche) Verteilt dann jeden zusätzlichen Speicherplatz proportional basierend auf dem Unterschied zwischen dem längsten Wort und dem längsten vollständigen Zelleninhalt. Ich würde diese Produktion nicht als fertig bezeichnen, da es sich um einen Proof-of-Concept handelt, aber ich hoffe, dass Sie (oder andere Suchende) sie als nützlichen Ausgangspunkt finden.

Der Schlüsselteil dafür ist folgender: $tablebuilder->determine_column_widths_by_minimum_strategy('100%', 'aaa')

Der erste Parameter gibt uns die Größenreferenz an, mit der wir arbeiten (100% der Seite, da ich diese benötigte, um die Messungen nützlich zu machen), und der zweite enthält einige voreingestellte Füllzeichen, die zu unseren Messungen hinzugefügt werden können, um Textstil und Tabelle zu berücksichtigen Polsterungsunterschiede.

Hier ist eine Demo davon: https://b65sol.com/so/59517311_new.php

Die Klasse selbst ist hier verfügbar: https://github.com/b65sol/random-classes

Der Code für diese Demo ist hier:

<?php
require 'vendor/autoload.php';
include 'random-classes/html2pdf-full-table-optimizer.php';
use Spipu\Html2Pdf\Html2Pdf;

//First let's build a random table!
$wordlist = ['Chocolate', 'Cake', 'Brownies', 'Cupcakes', 'Coreshock', 'Battery', 'Lead', 'Acid', 'Remilia'];
$wordlist2 = ['Reinforcement Learning', 'Initial Latent Vectors', 'Bag-of-Words', 'Multilayer Perceptron Classifier',
  'Deconvolutional Neural Network', 'Convolutional Neural Network'];
$number_of_columns = rand(3,11);
$number_of_rows = rand(8, 15);
$possible_column_names = ['Unit', 'Description', 'Variable', 'Moon', 'Cheese', 'Lollipop', 'Orange', 'Gir', 'Gaz', 'Zim', 'Dib'];
$possible_column_content_generators = [
  function() {return rand(10,100); },
  function() {return rand(1000, 1999); },
  function() use ($wordlist) {return $wordlist[rand(0, count($wordlist)-1)]; },
  function() use ($wordlist) {return $wordlist[rand(0, count($wordlist)-1)] . ' '. $wordlist[rand(0, count($wordlist)-1)];},
  function() use ($wordlist2) {return $wordlist2[rand(0, count($wordlist2)-1)];},
];

shuffle($possible_column_names);
$list_of_generators = [];
$column_classes = [];
$column_names = [];
for($i = 0; $i < $number_of_columns; $i++) {
  $list_of_generators[$i] = $possible_column_content_generators[rand(0, count($possible_column_content_generators)-1)];
  $column_classes[$i] = ['text-left', 'text-right', 'text-center'][rand(0,2)];
  $column_names[$i] = $possible_column_names[$i];
}
//Got our random stuff, onward to generator!

try {
    $html2pdf = new Html2Pdf('P', 'A4', 'en', true, 'UTF-8', 5);
    $html2pdf->pdf->SetDisplayMode('real');
    $tablebuilder = new Html2PdfTableOptimizer($html2pdf->pdf, '11px', 'helvetica');

    //run table builder... using random data for testing.
    for($i = 0; $i < $number_of_columns; $i++) {
      /*Add a header cell, content is the first parameter, CSS class attribute is second.*/
      $tablebuilder->add_header_cell($column_names[$i], $column_classes[$i] . ' bg-dark text-white');
    }

    for($i = 0; $i < $number_of_rows; $i++) {
      //Start a row.
      $tablebuilder->start_data_row();
      for($col = 0; $col < $number_of_columns; $col++) {
        //Add content and our column classes for td elements
        $tablebuilder->add_data_row_cell($list_of_generators[$col](), $column_classes[$col]);
      }
      //End the row.
      $tablebuilder->end_data_row();
    }
    //Get the table HTML.
    $render = $tablebuilder->render_html();

    $newContent = '
      <style type="text/css">
      table{width:100%;}
      table, table td, table th{
          border-collapse: collapse;
          border: solid 1px #ababab;
      }
      .text-dark, table td{
          color: #343a40;
      }
      .text-white{
          color: #ffffff;
      }
      table td,
      table th {
          font-size: 11px;
          padding: 3px;
          line-height: 1.2;
          font-family:arial;
      }

      .bg-dark {
          background-color: #343a40;
      }
      .bg-secondary {
          background-color: #6c757d;
      }
      .bg-white {
          background-color: #ffffff;
      }
      .row-even {
        background-color: #d1d1d1;
      }
      .text-left {
          text-align: left;
      }
      .text-right {
          text-align: right;
      }
      .text-center {
          text-align: center;
      }

      '.$tablebuilder->determine_column_widths_by_minimum_strategy('100%', 'aaa').'

      </style>
      ';
      $newContent .= '<page>'.$render.'</page>';

      if(!empty($_GET['html'])) {
        echo $newContent;
      } else {
        $html2pdf->writeHTML($newContent);
        $PDFName = "ItemLists_".date('Y.m.d_H.i.s').".pdf";
        $html2pdf->output($PDFName, 'I');
      }
} catch (Html2PdfException $x) {
    $html2pdf->clean();

    $formatter = new ExceptionFormatter($x);
    echo $formatter->getHtmlMessage();
}

ENDE DES UPDATE


Wenn Sie die Breiten nicht explizit angeben möchten, können Sie TCPDFs writeHTMLanstelle der Html2PDFBibliothek verwenden. Sie müssen jedoch nur gleich große Spalten verwenden. Ich dachte tatsächlich, es würde eine Neuberechnung der Spaltengrößen bewirken, wenn Sie nur eine oder zwei angeben würden, aber ich war falsch. Darüber hinaus weist TCPDF einige der gleichen Einschränkungen auf wie Html2PDF- Wenn Sie die Größe einer Spalte angeben, wird die Größe der anderen Spalten nicht automatisch angepasst.

Außerdem werden Spalten nicht wie bei einem Browser an den Inhalt angepasst. Das ist eigentlich ziemlich schwer zu machen, also bin ich nicht überrascht, dass TCPDF es nicht versucht. Eine potenziell mühelose Lösung wäre, Ihre Spalten mit einem Größenanteil zu versehen und die Breite im laufenden Betrieb für jede Spalte zu berechnen, je nachdem, wie viele Spalten jeder proportionalen Größe ausgewählt sind. (z. B. sind numerische Spalten 'klein', und eine Beschreibungsspalte wäre 'groß', sodass zwei kleine Spalten zu je 10% und eine einzelne Beschreibung zu 80% aufgeteilt werden. Zwei kleine Spalten zu 5% und große Spalten zu 45%. jeweils. Es würde einige Experimente erfordern.)

EPB
quelle
Vielen Dank für Ihre Zeit, das Problem ist, dass ich eine dynamische Tabelle verwende. Es gibt 10 Spalten, die von den Benutzern ausgewählt werden können, vielleicht 5 Spalten oder 8 Spalten oder vielleicht 2 Spalten, die optional sind. Es gibt eine andere Möglichkeit, wie ich es tun kann und es ist : table th, table td { <?=floor(100 / count($cols))?>%;}aber ich suche nach einer besseren Lösung
Mohsen Newtoa
1
Wie engagiert Html2PDFbist du? Alle meine Lektüre des Codes und der Beispiele legen nahe, dass dies der einzige Weg ist. TCPDF kann dies mit einer etwas weniger leistungsfähigen CSS-Analyse tun, verfügt jedoch über ein besseres Layoutsystem. Ich kann Markup für TCPDF vorschlagen.
EPB
Ich habe TCPDF ausprobiert und festgestellt, dass sie dieselbe Methode wie ich verwenden, aber mein Problem wird dadurch immer noch nicht gelöst. Wenn ich eine Zelle ändere, wirkt sich dies auf die anderen Zellen aus und die Tabellenbreite passt immer noch nicht zur Seite. Der Unterschied zwischen TCPDF und HTML2PDF besteht darin, dass TCPDF genau wie ich die Standardtabellengröße verwendettable th, table td { <?=floor(100 / count($cols))?>%;}
Mohsen Newtoa
Das ist in der Tat das Problem, auf das ich auch gestoßen bin. Ich dachte, es würde mir erlauben, die Größe nur bestimmter zu spezifizieren und den Rest automatisch anzupassen, wenn ich meinen Test einrichte (was zwar nicht ideal wäre, aber mit wenig Aufwand einigermaßen gut aussehen würde), aber es tut es überhaupt nicht . Ich werde ein bisschen mehr graben und sehen, ob es eine Möglichkeit gibt, die Spalten mit geringem Aufwand automatisch zu dimensionieren. Es müsste sich jedoch um eine Art Vorverarbeitung handeln, da weder noch Html2PDFoder wie es TCPDFscheint.
EPB
Ich bin mir nicht sicher, ob Sie über Aktualisierungen informiert werden, aber ich habe eine Klasse hinzugefügt, die textbasierte Tabellen basierend auf ihrem Inhalt dynamisch skaliert. Es gibt auch eine Strategie namens determine_column_widths_evenly, mit der Sie einige bekannte Größen angeben und den verbleibenden Speicherplatz gleichmäßig verteilen können.
EPB
0

Die Arbeit mit der serverseitigen PDF-Datei eignet sich nicht für CSS. Haben Sie versucht, nur HTML zu verwenden?

Zum Beispiel:

<table width="100%">
  <!-- your table code -->
</table>

Alternativ können Sie versuchen:

<table style="width: 100%;">
  <!-- your table code -->
</table>

Hier ist ein CodePen, der dies im Browser demonstriert. https://codepen.io/tinacious/pen/PowJRbb

Tina
quelle
Ich habe all dies ausprobiert: <table width="100%"> <table style="width:100%;"> <table class="w100"> <link rel="stylesheet" href="style.css" />aber das Problem ist, dass es unter HTML gut funktioniert, aber wenn ich es als PDF speichern möchte, wird es wie das Bild sein.
Mohsen Newtoa
0

das Bild: Geben Sie hier die Bildbeschreibung ein

Ich denke, der beste Weg für diese Art von Tabellen ist folgende:

table th, table td { width:<?=floor(100 / count($cols))?>%;}

Auf TCPDF haben sie nichts Besonderes gemacht, die Tabelle passt sowieso nicht auf die Seite.

Mohsen Newtoa
quelle