Sara: html2Pdf

Hallo,

ich erzeuge eine PDF mit dem HTML2PDF Tool, klappt eigentlich relativ gut. Jetzt habe ich ein Problem, sobald es mehr Inhalt ist und ich dafür zwei oder mehr Seiten brauche kommt folgende Fehlermeldung:

[Thu Nov 05 23:15:22 2015] [error] [client xx.xx.xx.xx] PHP Fatal error:  Uncaught <span style="color: #AA0000; font-weight: bold;">Fehler n\xc2\xb07</span><br>Datei : /WebSeite/include/lib/html2pdf/html2pdf.class.php<br>Linie : 5524<br><br>Er Inhalt eines TD-Tag passt nicht nur auf einer Seite

[Thu Nov 05 23:15:22 2015] [error] [client xx.xx.xx.xx]   thrown in /WebSeite/include/lib/html2pdf/html2pdf.class.php on line 5524

Das ganze muss man leider mit Tabelle aufbauen und klar, wenn eine Tabelle nicht mehr auf eine Seite passt muss diese wohl irgendwie getrennt werden, keine Ahnung wie ich dieses umsetzten kann :/

  1. Hallo,

    vielleicht sollte ich mich von HTML2PDF verabschieden und auf http://pxd.me/dompdf/www/index.php setzten. Dieses Tool kommt scheinbar auch mit großen Tabelle aus.

    1. vielleicht sollte ich mich von HTML2PDF verabschieden und auf http://pxd.me/dompdf/www/index.php setzten. Dieses Tool kommt scheinbar auch mit großen Tabelle aus.

      Viele HTML-zu-PDF-Übersetzer teilen sich den gewaltigen Nachteil, dass sie das Zeichnen vollständig selber übernehmen. Deshalb wirst du auch bei all diesen Bibliotheken eine lange Liste von HTML/CSS-Features finden die nicht unterstützt werden, oder meistens sogar nur eine kurze Liste von Features, die unterstützt werden. Für dieses Problem besteht auch kaum Hoffnung auf Besserung, solange die Entwickler versuchen, das Rendering eigenständig zu bewältigen. Die Rendering-Engine ist vermutlich die umfangreichste Komponente eines Browsers, und selbst aktuelle Browserhersteller haben Schwierigkeiten damit, neue Features zeitnah umzuzusetzen. Die Lösung hierfür ist es, das Rendering an die Rendering-Engine eines echten Browsers zu delegieren und diese Ausgabe dann in PDF zu konvertieren. wkhtml2pdf ist ein Werkzeug, das intern von einem WebKit-Browser Gebrauch macht. Damit habe ich persönlich sehr gute Erfahrungen gemacht, die Bibliothek bietet dem Entwickler die Möglichkeit eine Browser-Umgebung zu konfigurieren (zum Beispiel Display-Größe und Auflösung) und rendert dann mit diesen emulierten Einstellungen die Seite. Das Ergebnis ist anschaulich, braucht aber trotzedem noch ein paar manuelle Tweaks, die zum größten Teil darauf zurück zu führen sind, dass WebKit-Browser bis heute keine vernünftige Unterstützunf für CSS' Druckeigenschaften bieten. Es gibt sogar einen PHP-Wrapper dafür.

  2. Guten Morgen,

    was ich nicht verstehe, warum versteht eine PDF Datei folgendes nicht:

    <?php
    ob_start();
    session_start(); 
    require_once 'include/lib/html2pdf/html2pdf.class.php';
    require_once 'include/lib/Swift-5.0.3/lib/swift_required.php';
    ?>
    
    .test1 {width: 200px; height: 200px; background: #efefef; float: left;}
    .test2 {width: 200px; height: 200px; background: #999999; float: left;}
    
    <div class="test1"></div>
    <div class="test2"></div>
    
    <?php
    $content = ob_get_clean();
    $pdf = new HTML2PDF('p','A4','de','UTF-8');
    $pdf->writeHTML($content);
    $pdf->Output('Unterschrift.pdf', 'D');
    ?>
    

    Wenn ich mir die PDF Datei anschaue die erzeugt wird, kommt dieses dabei raus

    Alternativ-Text

    Ich verstehe es einfach nicht. Andere Shops und Webseiten erzeugen doch auch mehrseitigen PDF Dateien, die ein schönes Design haben.

    Bin bei html2PDF erstmal geblieben

    1. Tach!

      was ich nicht verstehe, warum versteht eine PDF Datei folgendes nicht:

      Eine PDF-Datei versteht weder PHP noch HTML noch CSS. HTML2PDF ist auch kein Zauberer. Es muss das HTML nebst CSS lesen, parsen und entsprechend von Regeln in das PDF-Format umsetzen. Wenn es keine Unterstützung von bestimmten Merkmalen von HTML oder PDF nicht implementiert hat, kann auch kein anderer zaubern. Du kannst dann nur die Dinge meiden, die nicht das gewünschte Ergebnis bringen und (einfachere) Alternativen suchen.

      Ich verstehe es einfach nicht. Andere Shops und Webseiten erzeugen doch auch mehrseitigen PDF Dateien, die ein schönes Design haben.

      Die verwenden vielleicht ein anderes Werkzeug. TCPDF vielleicht, aber damit hat man mehr Handarbeit als einfach nur ein HTML zu übergeben.

      dedlfix.

      1. Hallo,

        Eine PDF-Datei versteht weder PHP noch HTML noch CSS. HTML2PDF ist auch kein Zauberer. Es muss das HTML nebst CSS lesen, parsen und entsprechend von Regeln in das PDF-Format umsetzen. Wenn es keine Unterstützung von bestimmten Merkmalen von HTML oder PDF nicht implementiert hat, kann auch kein anderer zaubern. Du kannst dann nur die Dinge meiden, die nicht das gewünschte Ergebnis bringen und (einfachere) Alternativen suchen.

        und warum steht dann auf La liste des styles CSS utilisables est la suivante float? Also muss es irgendwie unterstützt werden.

        Eine alternative suche ich schon seit gestern Nachmittag, leider scheitert es immer wenn ich mehr viele Tabellen habe, die nicht mehr auf eine Seite passen, was bei einem Dokument sehr schnell vorkommen kann.

        1. Hallo

          wie dedlfix bereits richtig geschrieben hat haben PDF und HTML/CSS nichts miteinander zu tun, außer dass die eventuell die gleichen Informationen enthalten sollen.

          Das geht schon damit los, dass PDF ähnlich Papierformaten eine Größe hat, Webseiten jedoch nicht.

          Aus diesem Grund können nur sehr einfache HTML-/CSS-Seiten automatisch in PDF-Dateien umgewandelt werden.

          Deshalb ist es sinnvoller, die Informationen zunächst in einer Datenbank zu speichern und daraus dann die Ausgabeformate wie PDF, HTML oder auch andere zu erstellen.

          Gruss

          MrMurphy

          1. Hallo,

            die Daten kommen ja auch aus einer Datenbank. Wie bereits geschrieben sobald ich sehr viele Einträge habe (mehr als eine Seite) habe ich ein Problem, dass der Server ein Fehler meldet wie du im ersten Posting sehen kannst.

            Solange ich nur 3-4 Positionen im PDF haben alles schön, funktioniert wunderbar. Sobald aber 5-x dazukommen geht nichts mehr.

            Ich kann auch mit HTML2PDF neue Seiten innerhalb einer Datei erzeugen und zwar mit

            <page pageset="old">
            </page>
            

            Auch dieses klappt, nur wie bekomme ich meine Datenbankinhalte auf zwei Seiten verteilt? Ich müsste dann meine

            foreach($user as $array){ }
            

            irgendwie unterbrechen und ein neues

            <page pageset="old">
            </page>
            

            einfügen?

            1. Moin,

              Wie bereits geschrieben sobald ich sehr viele Einträge habe (mehr als eine Seite) habe ich ein Problem, dass der Server ein Fehler meldet wie du im ersten Posting sehen kannst.

              das ist nicht der Server, der da einen Fehler meldet, sondern PHP - genauer, das Script selbst, das eine Exception wirft. Noch dazu mit falschem Wortlaut: Nicht der Inhalt des td-Tags ist hier gemeint, sondern der Inhalt eines td-Elements.
              Aber lassen wir das mit den Korinthen für den Moment.

              Ich kann auch mit HTML2PDF neue Seiten innerhalb einer Datei erzeugen und zwar mit

              <page pageset="old">
              </page>
              

              Ja prima, dann wäre doch alles in Ordnung.

              Auch dieses klappt, nur wie bekomme ich meine Datenbankinhalte auf zwei Seiten verteilt? Ich müsste dann meine

              foreach($user as $array){ }
              

              irgendwie unterbrechen und ein neues

              <page pageset="old">
              </page>
              

              einfügen?

              Ja, zum Beispiel. Und? MrMurphy1 hat schon darauf hingewiesen: PDF ist auf eine einmal festgelegte Seitengröße fixiert, das Dokument dehnt sich nicht bei Bedarf aus wie bei HTML. Das musst du berücksichtigen. Du musst also etwa abschätzen (oder festlegen), wie groß die einzelnen Felder/Boxen sind und den Platzbedarf mitzählen. Sobald du eine bestimmte Länge erreicht hast, fügst du einen Seitenumbruch ein (dabei ggf. Fuß- und Kopfzeile mit berücksichtigen).

              Das ist nicht ganz trivial, zugegeben, aber es ist auch nicht gerade "rocket science".

              So long,
               Martin

              1. Hallo,

                <page pageset="old">
                </page>
                

                Ja prima, dann wäre doch alles in Ordnung.

                alles in Ordnung? Für mich leider noch überhaupt nicht. Bis jetzt weiß ich nur, wenn ich <page pageset=old"> nach dem ersten </page> anfüge habe ich eine zweite Seite.

                Ja, zum Beispiel. Und? Das ist nicht ganz trivial, zugegeben, aber es ist auch nicht gerade "rocket science".

                Und? Da meine PHP Kenntnisse nicht gerade die besten sind und ich sehr viel Google muss habe ich damit doch ein sehr großes Problem. Ich zeig einfach mal meinen PHP Code, der nur für das PDF zuständig ist (wie gesagt solange alles auf eine Seite passt, alles wunderbar)

                <!-- Kann immer stehen bleiben, selbst bei <page pageset="old"></page> wird es richtig eingefügt -->
                <page backtop="1%" backbottom="2%" backleft="5%" backright="5%">
                  <page_footer style="text-align:center; line-height:14px; font-size:10px; height:300px;">
                  <?php echo nl2br(htmlspecialchars($text_unten));?>
                  </page_footer>
                
                <!-- Tabelle um die ganze Seite -->
                <table style="width: 100%;">
                  <tr> 
                    <!-- Tabellenspalte für die Linke Seite -->
                    <td style="width: 70%;">
                      <h1 style="margin-top:42px; margin-bottom:30px; font-size:36px"><?php echo $titel;?></h1>
                      <div style="line-height:22px; margin-top:10px;">
                        <?php echo htmlspecialchars($Export->firma); ?><br>
                        <?php echo htmlspecialchars($Export->titel); ?> <?php echo htmlspecialchars($Export->vorname . " ". $Export->name); ?><br>
                        <?php echo htmlspecialchars($Export->strasse); ?><br>
                        <?php echo htmlspecialchars($Export->plz); ?> <?php echo htmlspecialchars($Export->ort); ?>
                      </div>
                
                      <div style="margin-top:50px;">
                        <div><?php echo nl2br($text_oben);?></div>
                      </div>
                      <!-- Hier wird die zweite Tabelle gefüllt um den Inhalt auszulesen -->
                      <table style="width: 95%;">
                          
                          <thead>
                            <tr>
                              <th style="width:9%; text-align:left; padding-bottom:20px;">Pos</th>
                              <th style="width:89%; text-align:left; padding-bottom:20px;">User</th>
                            </tr>
                          </thead>
                
                          <tbody>
                          <!-- Hier beginnt die Schleife -->
                          <?php $pos = 1; 
                                  foreach($UserAusgabe as $array)
                          { ?>  
                            <tr style="height:1.5em;">
                              <td style="width:9%; text-align:left; vertical-align:top;"><?php echo $pos;?></td>
                              <td style="width:89%; text-align:left; vertical-align:top;">
                                <div style="padding-bottom:10px"><?php echo htmlspecialchars($array['UserName']); ?></div>
                                <br><br>
                              </td>
                            </tr>
                          <?php
                          $pos++;
                          } ?>        
                          </tbody>
                            
                    </table>
                        
                  </td>
                  <!-- Hier beginnt die Tabelle für die rechte Spalte -->
                  <td style="width: 30%; vertical-align:top;">
                
                    <div style="margin-bottom:22px;"><img src="logo.jpg"></div>
                    <div style="line-height:20px; padding-left:5px;">Datum:&nbsp;&nbsp; <?php echo $datum;?><br></div>
                
                    <div style="margin-top:42px; padding-left:5px;">
                      <strong><?php echo $seite; ?></strong><br>
                      <?php echo $strasse; ?><br>
                      <?php echo $ort;?>
                      <br><br>
                      Fon: <?php echo $telefon; ?><br>
                      Fax:&nbsp;<?php echo $fax;?>
                      <br><br>
                      Mail:&nbsp;&nbsp;<?php echo $email;?><br>
                      Web:&nbsp;<?php echo $webseite;?>
                      </div>
                          
                  </td>   
                  </tr>
                </table>
                </page> 
                

                Ich habe auch schon genau ausgerechnet wenn das Problem auftritt. 4 Einträge passen auf eine Seite, ab dem 5 tritt der Fehler auf. Das schöne? daran ist, die Einträge sind zu 100% vom Inhalt immer gleich. Also darauf müsste keine Rücksicht genommen werden.

                Und bevor jetzt einer kommt und sagt warum ich hier inline CSS nutzte, ich kann leider im PDF kein externes CSS Anwenden daher inline!

                Mein Problem ist also folgendes

                Ich weiß wie viele Einträge in der Datenbank sind, diesen Wert erhalte ich mit $SummeUserDBPDF derzeit steht hier z.B. eine 6 drin.

                In meiner foreach($UserAusgabe as $array) lese ich natürlich alle Einträge aus, hier müsste denke ich irgendetwas geändert werden dass ich im ersten Durchlauf nur 4 Einträge erhalte

                Allerdings muss bereits hier

                <!-- Tabelle um die ganze Seite -->
                <table style="width: 100%;">
                

                berücksichtigt werden, wenn mehr als 4 Einträge vorhanden sind, muss eine weitere Seite unten angefügt werden und zwar solange bis alle Einträge ihren Platz haben, bei z.B. 40 Einträge, müssen 10 Seiten a 4 Einträge angefügt werden. Gleichzeig muss aber der ganze Krempel sprich alles ab <!-- Tabelle um die ganze Seite --> ebenfalls kopiert werden und in die jeweiligen neuen Pages eingefügt werden und zu guter letzt muss das foreach wissen wo es sich derzeit befindet.

                Sorry wenn alles etwas länger und vielleicht auch durcheinander rüber gekommen ist. Im erklären bin ich nicht wirklich gut :/ Hoffentlich kann mir jemand bei diesem schwierigen Problem helfen.

                1. Tach!

                  Und bevor jetzt einer kommt und sagt warum ich hier inline CSS nutzte, ich kann leider im PDF kein externes CSS Anwenden daher inline!

                  Es kommt bei der Aufgabenstellung nicht drauf an, was irgendwelche HTML/CSS-Evangelisten für im Browser darzustellende Dokumente predigen. Du willst eine Ausgabe auf einem Papierformat haben, und für die musst du andere Bedingungen berücksichtigen. Das fängt von einer eventuell anderen Aufteilung/Anordnung der Inhalte an und hört bei den dafür im Hintergrund zu verwendenden Anweisungen nicht auf.

                  HTML ist nicht dafür ausgelegt, Papierseiten zu gestalten. Es ist daher eine ziemliche Krücke, wenn du versuchst, über den HTML-Umweg aus den Daten ein PDF zu erzeugen. Du bist flexibler und kannst genauer das Ergebnis beeinflussen, wenn du zum Beispiel TCPDF nimmst. Das ist aber auch ein Stück weit herausfordernder, als es HTML ist. Der Grund ist, dass du dich genauer mit den Gegebenheiten von Papier beschäftigen musst. Alles was du zu HTML gelernt hast, ist nur bedingt bis gar nicht für das Papier zu gebrauchen.

                  In meiner foreach($UserAusgabe as $array) lese ich natürlich alle Einträge aus, hier müsste denke ich irgendetwas geändert werden dass ich im ersten Durchlauf nur 4 Einträge erhalte

                  Wie wäre es mit mitzählen?

                  Allerdings muss bereits hier [...] berücksichtigt werden, wenn mehr als 4 Einträge vorhanden sind,

                  ... oder erstmal die Daten holen, zwischenspeichern, sie zählen und dann verarbeiten?

                  Das ist auch eine Art Gruppenwechsel, dafür gibt es einen Artikel in unserem Wiki.

                  dedlfix.

                2. Hi,

                  alles in Ordnung? Für mich leider noch überhaupt nicht. Bis jetzt weiß ich nur, wenn ich <page pageset=old"> nach dem ersten </page> anfüge habe ich eine zweite Seite.

                  und ich dachte, das zu wissen würde genügen.

                  Ja, zum Beispiel. Und? Das ist nicht ganz trivial, zugegeben, aber es ist auch nicht gerade "rocket science".

                  Und? Da meine PHP Kenntnisse nicht gerade die besten sind ...

                  Sorry, dann habe ich dich falsch eingeschätzt. Du hast dich hier in letzter Zeit in anderen Threads so eifrig und oft richtig und hilfreich engagiert, dass ich gute PHP-Kenntnisse einfach vorausgesetzt habe.

                  Ich zeig einfach mal meinen PHP Code, der nur für das PDF zuständig ist

                  Okay, und ich geb mal meinen Senf dazu. ;-)

                  <!-- Kann immer stehen bleiben, selbst bei <page pageset="old"></page> wird es richtig eingefügt -->
                  <page backtop="1%" backbottom="2%" backleft="5%" backright="5%">
                    <page_footer style="text-align:center; line-height:14px; font-size:10px; height:300px;">
                    <?php echo nl2br(htmlspecialchars($text_unten));?>
                    </page_footer>
                  

                  Stopp. Dieser Abschnitt scheint zwar okay zu sein, aber ein genereller Rat: PDF ist ein Print-ähnliches Ausgabeformat. Deswegen ist es hier sinnvoll, mit absoluten Maßeinheiten wie mm oder pt (etwa bei Schriftgrößen) zu hantieren - also genau das, was man bei Webseiten normalerweise nicht tun möchte.

                  Auch das folgende Tabellenlayout würde ich normalerweise kritisieren; als Zwischenstufe zur Erzeugung eines PDF-Dokuments ist es aber IMO in Ordnung.

                            <tbody>
                            <!-- Hier beginnt die Schleife -->
                            <?php $pos = 1; 
                                    foreach($UserAusgabe as $array)
                            { ?>  
                              <tr style="height:1.5em;">
                                <td style="width:9%; text-align:left; vertical-align:top;"><?php echo $pos;?></td>
                                <td style="width:89%; text-align:left; vertical-align:top;">
                                  <div style="padding-bottom:10px"><?php echo htmlspecialchars($array['UserName']); ?></div>
                                  <br><br>
                                </td>
                              </tr>
                            <?php
                            $pos++;
                            } ?>        
                            </tbody>
                  

                  Nochmal Stopp. Das ist doch genau der Knackpunkt. Und wie praktisch: Du lässt sowieso schon einen Zähler mitlaufen! Eine Quick'n'Dirty-Lösung könnte also sein, unmittelbar nach dem Erhöhen von $pos abzufragen, ob $pos durch 4 teilbar ist, also (($pos%4)==0) ist. Wenn ja, gibst du einmal das ganze Geraffel (Tabellen beenden, Seite beenden, neue Seite beginnen, Kopfzeile und Tabellengerüst neu ansetzen) aus, was zum Beenden und Neu-Beginnen einer Seite nötig ist.

                  Schön ist das von der Code-Struktur aber nicht. Schöner wäre IMO, ganz zu Anfang die Anzahl der Einträge zu ermitteln (die kriegst du ja mit count($UserAusgabe) leicht raus), und dann eine äußere Schleife um die gesamte Ausgabe zu legen, die von 0 bis count($UserAusgabe)/4-1 läuft. Dann ist noch etwas Detailarbeit nötig; so müssen etwa innerhalb der Schleife dann alle $pos durch $pos+4*$seite ersetzt werden. Außerdem geht die elegante Iteration mit foreach() dann nicht mehr, sondern du müsstest eine konventionelle for-Schleife mit einem numerischen Index benutzen. Dabei beachten, dass Array-Indexe normalerweise ab 0 zählen, du beginnst mit $pos aber bei 1.

                  Ich skizziere nur mal die Grobstruktur in Pseudocode, wie ich es angehen würde. Ganz anders, aber vielleicht taugt es als Inspiration.

                  datenbankabfrage();                           // alle Datensätze holen
                  for ($i=0; $i<count($daten); $i++)            // über alle Datensätze iterieren
                   { datensatz = $daten[$i];                    // aktueller Datensatz pro Durchlauf
                     $seite = ($i/4) + 1;                       // Seitennummer
                     $posnr = $i+1;                             // Positionsnummer des Datensatzes
                     if (($i%4)==0))                            // ist $i durch 4 teilbar?
                      { beginneneueseite();                     // neue Seite (<page>, Kopfzeile, Tabellengerüst)
                      }
                     erzeugeausgabe($posnr, $datensatz);        // aktuellen Datensatz ausgeben
                     if (($i%4)==3)                             // Ergibt $i/4 den Divisionsrest 3
                      || $i==count($daten)-1)                   // oder sind wir im letzten Durchlauf?
                      { beendeaktuelleseite();                  // Tabelle abschließen, </page>
                      }
                   }
                  

                  Und bevor jetzt einer kommt und sagt warum ich hier inline CSS nutzte, ich kann leider im PDF kein externes CSS Anwenden daher inline!

                  Geschenkt. Finde ich zwar nicht schön, aber wenn's denn so ist ...

                  Ich weiß wie viele Einträge in der Datenbank sind, diesen Wert erhalte ich mit $SummeUserDBPDF derzeit steht hier z.B. eine 6 drin.

                  Ah, also ist die Abfrage mit count() sogar überflüssig.

                  So long,
                   Martin

                  1. Hallo,

                    danke für deine sehr ausführliche Erklärung. Ich habe jetzt 3 Stunden versucht gemacht und getan, alles hat nicht geklappt. Ich muss mir irgendetwas anderes einfallen lassen. Im schlimmsten Fall muss ich die PDF Dateien von Hand füllen, was natürlich sehr viel Arbeit ist, aber ich kann nicht ständig mein halbes Projekt zerstören, weil wieder etwas schief gelaufen ist.

                  2. Hallo,

                    nochmals eine Frage, ich habe mein Code jetzt mal sehr stark gekürzt

                    
                    $SummeUserDBPDF = 6
                    
                    <page backtop="1%" backbottom="2%" backleft="5%" backright="5%"> 
                    	<page_footer style="text-align:center; line-height:14px; font-size:10px; height:300px;">
                               Hier kommt der Footer rein
                    	</page_footer>
                    	Hier kommt die erste Tabelle rein mit 4 Einträgen
                    </page>
                    
                    <page></page>
                    

                    Der erste <page></page> soll IMMER geladen werden, denn ein PDF wird nur erstellt, wenn mindestens ein Eintrag vorhanden ist.

                    Der zweite <page></page> Abschnitt soll so oft wiederholt werden, bis $SummeUserDBPDF = 6 nicht mehr durch 4 geteilt werden kann, in diesem Fall einmal, denn die ersten 4 Einträge sind ja bereits in der ersten <page> verarbeitet

                    1. Hi,

                      nochmals eine Frage, ich habe mein Code jetzt mal sehr stark gekürzt

                      das ist immer eine gute Idee. Wenn die vereinfachte Lösung dann wirklich läuft, kann man Schritt für Schritt wieder ergänzen.

                      $SummeUserDBPDF = 6
                      
                      <page backtop="1%" backbottom="2%" backleft="5%" backright="5%"> 
                      	<page_footer style="text-align:center; line-height:14px; font-size:10px; height:300px;">
                                 Hier kommt der Footer rein
                      	</page_footer>
                      	Hier kommt die erste Tabelle rein mit 4 Einträgen
                      </page>
                      
                      <page></page>
                      

                      Der erste <page></page> soll IMMER geladen werden, denn ein PDF wird nur erstellt, wenn mindestens ein Eintrag vorhanden ist.

                      Du denkst immer noch umständlich. Versuche dich von der Idee zu lösen, dass man den Fall "erste Seite" anders behandeln müsste als "zweite und folgende Seiten". Versuche noch einmal zu verstehen, was ich dir mit dem Beispiel in Pseudocode klarmachen wollte:

                      • Du gehst einfach der Reihe nach deine Datensätze durch, vom ersten bis zum letzten.
                      • Vor der Ausgabe des aktuellen Datensatzes muss eine neue Seite begonnen werden, falls die Datensatznummer (günstigerweise ab 0 gezählt) durch 4 teilbar ist, also bei 0, 4, 8, ...
                      • Nach der Ausgabe des aktuellen Datensatzes muss die aktuelle Seite beendet werden, falls die Datensatznummer beim Dividieren durch 4 den Rest 3 ergibt, also bei 3, 7, 11, ...

                      Das ist eigentlich der ganze Trick dabei. Wenn man es von Anfang an flexibel machen möchte, kann man die 4 (Datensätze pro Seite) auch noch variabel machen. Ich würde das tun. ;-)

                      Warum tust du dich mit diesem Denkansatz so schwer? Wo liegt konkret das Verständnisproblem?

                      So long,
                       Martin

                      1. Hallo,

                        Du denkst immer noch umständlich. Versuche dich von der Idee zu lösen, dass man den Fall "erste Seite" anders behandeln müsste als "zweite und folgende Seiten". Versuche noch einmal zu verstehen, was ich dir mit dem Beispiel in Pseudocode klarmachen wollte:

                        • Du gehst einfach der Reihe nach deine Datensätze durch, vom ersten bis zum letzten.
                        • Vor der Ausgabe des aktuellen Datensatzes muss eine neue Seite begonnen werden, falls die Datensatznummer (günstigerweise ab 0 gezählt) durch 4 teilbar ist, also bei 0, 4, 8, ...
                        • Nach der Ausgabe des aktuellen Datensatzes muss die aktuelle Seite beendet werden, falls die Datensatznummer beim Dividieren durch 4 den Rest 3 ergibt, also bei 3, 7, 11, ...

                        Warum sollte ich mich von dem Gedanken verabschieden dass die zweite Seite anderes behandelt werden soll / muss? Dieses möchte ich nicht, dieses schreibt mir HTML2PDF so vor. Die erste Seite muss so aufgebaut sein

                        <page backtop="1%" backbottom="2%" backleft="5%" backright="5%"> 
                        	<page_footer>
                            	<p>Hier kommt der Footer rein</p>
                        	</page_footer>
                        	Hier kommt die erste Tabelle rein mit 4 Einträgen
                        </page>
                        

                        Dass HTML2PDF die zweite Seite an die erste Seite hängt, muss die zweite Seite so beginne:

                        <page pageset="old">Hier dann die Tabelle usw.</page>
                        

                        Habe ich später also 2 Seiten, weil 6 Einträge vorhanden sind, muss mein HTML so aussehen

                        <page backtop="1%" backbottom="2%" backleft="5%" backright="5%"> 
                                <page_footer>
                                    <p>Hier kommt der Footer rein</p>
                                </page_footer>
                                Hier kommen die ersten 4 Einträge rein = Seite 1
                        </page>
                        <page pageset="old">
                        Hier kommen die letzten 2 Einträge rein = Seite 2
                        
                        </page>
                        

                        Hätte ich jetzt 12 Einträge würde es so lauten

                        <page backtop="1%" backbottom="2%" backleft="5%" backright="5%"> 
                          <page_footer>
                           <p>Hier kommt der Footer rein</p>
                          </page_footer>
                           <p>Hier kommen die ersten 4 Einträge rein = Seite 1</p>
                        </page>
                        <page pageset="old">
                           <p>Hier kommen die zweiten 4 Einträge rein = Seite 2</p>
                        </page>
                        <page pageset="old">
                           <p>Hier kommen die dritten 4 Einträge rein = Seite 2</p>
                        </page>
                        

                        Das heißt also die erste kann und muss immer gleich aussehen. Die zweite und weitere werden einfach unterhalb der ersten angehängt.

                        Warum tust du dich mit diesem Denkansatz so schwer? Wo liegt konkret das Verständnisproblem?

                        Ich weiß es nicht, mir fehlt einfach das Verständnis. An dem Problem sitze ich jetzt seit gestern Abend 19 Uhr.

                        1. Hallo Sara,

                          Warum sollte ich mich von dem Gedanken verabschieden dass die zweite Seite anderes behandelt werden soll / muss?

                          weil ich diesen Rat auf das Große Ganze bezogen und Details in der Umsetzung möglicherweise übersehen habe.

                          Dieses möchte ich nicht, dieses schreibt mir HTML2PDF so vor. Die erste Seite muss so aufgebaut sein

                          <page backtop="1%" backbottom="2%" backleft="5%" backright="5%"> 
                          	<page_footer>
                              	<p>Hier kommt der Footer rein</p>
                          	</page_footer>
                          	Hier kommt die erste Tabelle rein mit 4 Einträgen
                          </page>
                          

                          Dass HTML2PDF die zweite Seite an die erste Seite hängt, muss die zweite Seite so beginne:

                          <page pageset="old">Hier dann die Tabelle usw.</page>
                          

                          Okay, gut. Jetzt kommen wir weiter, glaube ich. Ich kenne das Tool html2pdf nur dem Namen nach, deswegen war mir das nicht bekannt bzw. war diese Rückinfo von dir sehr wichtig. Die erste Seite muss sich also in der Direktive <page ...> von den folgenden unterscheiden - bei der ersten Seite werden vermutlich Ränder definiert, bei den folgenden Seiten gibt man quasi nur an "wie bisher auch schon".
                          Wird der Footer bei Folgeseiten auch weggelassen und dadurch automatisch wiederholt?

                          Anyway, aber dann muss ich doch - wenn ich mal bei meinem Modell bleibe - auch nur am Anfang der Schleife, also da, wo ich eine neue Seite beginne, mit einem einfachen if abfragen, ob $pos (oder $i oder wie immer die Schleifenvariable heißen möchte) gleich 0 ist. Wenn ja, bin ich am Anfang der ersten Seite und muss den ausführlichen Block ausgeben:

                          <page backtop="1%" backbottom="2%" backleft="5%" backright="5%"> 
                          	<page_footer>
                              	<p>Hier kommt der Footer rein</p>
                          	</page_footer>
                          

                          Andernfalls bin ich am Anfang von Seite 2,3,4... und ich muss die verkürzte Form des Seitenanfangs ausgeben:

                          <page pageset="old">
                          

                          Der Rest ist aber doch in beiden Fällen gleich. Oder nicht?

                          Habe ich später also 2 Seiten, weil 6 Einträge vorhanden sind, muss mein HTML so aussehen

                          Abgesehen davon, dass das kein HTML ist, ja. ;-)

                          Das heißt also die erste kann und muss immer gleich aussehen. Die zweite und weitere werden einfach unterhalb der ersten angehängt.

                          Das habe ich nun verstanden. Aber wie gesagt, das betrifft doch nur die für html2pdf gedachten Direktiven für den Seitenanfang, während der Inhalt (also nachher deine Tabellen und deren ganze Formatierung) und der Code fürs Seitenende dennoch gleich ist. Deswegen würde ich das nicht mit zwei getrennten Code-Abschnitten realisieren. Nicht wegen der Schreibarbeit, sondern weil es später leichter zu warten und zu pflegen ist: Eine Änderung des layouts muss ich dann nicht an zwei Stellen machen, sondern nur an einer.

                          Warum tust du dich mit diesem Denkansatz so schwer? Wo liegt konkret das Verständnisproblem?

                          Ich weiß es nicht, mir fehlt einfach das Verständnis. An dem Problem sitze ich jetzt seit gestern Abend 19 Uhr.

                          Hmm, schwierig. Um ein Problem zu lösen, muss man erstmal erkennen, worin es genau besteht.

                          So long,
                           Martin

                          1. Hallo,

                            Wird der Footer bei Folgeseiten auch weggelassen und dadurch automatisch wiederholt?

                            Genau der Footer wird auf allen Seiten einfach wiederholt. Möchte ich auf den Unterseiten einen anderen Footer haben, muss dieser ebenfalls mit in die <page pageset="old"></page>. Ist in meinem Fall nicht wichtig, denn der Footer soll auf allen Seiten gleich bleiben.

                            Anyway, aber dann muss ich doch - wenn ich mal bei meinem Modell bleibe - auch nur am Anfang der Schleife, also da, wo ich eine neue Seite beginne, mit einem einfachen if abfragen, ob $pos (oder $i oder wie immer die Schleifenvariable heißen möchte) gleich 0 ist. Wenn ja, bin ich am Anfang der ersten Seite und muss den ausführlichen Block ausgeben:

                            <page backtop="1%" backbottom="2%" backleft="5%" backright="5%"> 
                            	<page_footer>
                                	<p>Hier kommt der Footer rein</p>
                            	</page_footer>
                            

                            Andernfalls bin ich am Anfang von Seite 2,3,4... und ich muss die verkürzte Form des Seitenanfangs ausgeben:

                            <page pageset="old">
                            

                            Der Rest ist aber doch in beiden Fällen gleich. Oder nicht?

                            Nicht ganz, auf der ersten Seite ist z.B. auch die Adresse von dem jeweiligen User, der die Daten anfordert. Diese möchte ich nicht auch noch auf der zweiten Seite haben, du siehst also, auch wenn es später etwas aufwendiger ist zu pflegen bin ich flexibler wenn ich jede Page komplett habe.

                            Warum tust du dich mit diesem Denkansatz so schwer? Wo liegt konkret das Verständnisproblem?

                            Ich habe irgendwie Grundsätzlich Probleme mit Schleifen und hier kommen gleich mehrere mit ins Spiel. Jetzt sind wir ja erst bei der ersten, an die foreach die für die Datensätze später zuständig ist, möchte ich noch gar nicht denken :/

                            EDIT:

                            Bin ich da auf der richtigen Richtung?

                            <page backtop="1%" backbottom="2%" backleft="5%" backright="5%"> 
                              <page_footer style="text-align:center; line-height:14px; font-size:10px; height:300px;">
                                 <?php echo nl2br(htmlspecialchars($test));?>
                              </page_footer>
                             Hier kommt die erste Tabelle rein mit 4 Einträgen
                            </page>
                            
                            <?php 
                            
                            // Warum 4 - Weil die ersten 4 Jahr in der ersten Page bereits abgearbeitet sind?
                            $i = 4;
                            
                            while($i < 6)
                            {
                              echo "<page pageset=\"old\"></page>"; 
                              $i = $i += 4 ;
                            } 
                            ?>
                            

                            Wenn ich dieses ausführe, erhalte ich 2 Seiten, was eigentlich richtig ist?

                            Nachtrag:

                            Wenn ich while($i < 6) in while($i < 12) ändere, erhalte ich 3 Seiten, scheint also richtig zu funktionieren!

                            Sorry wenn ich vielleicht nerve, aber ich will es einfach verstehen und lernen. Wenn du sagst ich habe keine Lust mehr, kann ich dieses völlig verstehen und ich bin auch keinem böse.

                            1. Hi,

                              Der Rest ist aber doch in beiden Fällen gleich. Oder nicht?

                              Nicht ganz, auf der ersten Seite ist z.B. auch die Adresse von dem jeweiligen User, der die Daten anfordert. Diese möchte ich nicht auch noch auf der zweiten Seite haben, du siehst also, auch wenn es später etwas aufwendiger ist zu pflegen bin ich flexibler wenn ich jede Page komplett habe.

                              ja, okay. Das sind aber alles Dinge, die du am Anfang schon hättest erwähnen sollen, da sie eine "einfache", sprich: streng systematische Lösung schwerer machen.

                              Warum tust du dich mit diesem Denkansatz so schwer? Wo liegt konkret das Verständnisproblem?

                              Ich habe irgendwie Grundsätzlich Probleme mit Schleifen und hier kommen gleich mehrere mit ins Spiel. Jetzt sind wir ja erst bei der ersten, an die foreach die für die Datensätze später zuständig ist, möchte ich noch gar nicht denken :/

                              Okay. Die ganz normale Diskrepanz zwischen Programmierern und normalen Menschen. ;-)

                              Bin ich da auf der richtigen Richtung?

                              Der Ansatz sieht gut aus; ich streue nur mal hier und da noch einen Kommentar ein.

                              <page backtop="1%" backbottom="2%" backleft="5%" backright="5%"> 
                                <page_footer style="text-align:center; line-height:14px; font-size:10px; height:300px;">
                                   <?php echo nl2br(htmlspecialchars($test));?>
                                </page_footer>
                               Hier kommt die erste Tabelle rein mit 4 Einträgen
                               // Genauer: Mit höchstens 4 Einträgen, es können auch weniger sein.
                              </page>
                              
                              <?php 
                              
                              // Warum 4 - Weil die ersten 4 Jahr in der ersten Page bereits abgearbeitet sind?
                              $i = 4;
                              // Kann man machen, ist aber nicht elegant.
                              // Besser: Setze $i ganz zu Anfang der ersten Seite auf 0, und erhöhe in jedem
                              // Durchlauf der foreach-Schleife um 1 (i++).
                              
                              while($i < 6)
                              // Warum $i<6?
                              {
                                echo "<page pageset=\"old\"></page>"; 
                                $i = $i += 4 ;
                              // Siehe oben: Lieber einmal pro Schleifendurchlauf erhöhen.
                              } 
                              ?>
                              

                              Die Zeile $i = $i += 4; ist übrigens Unsinn. Sie funktioniert und liefert das, was du meinst, ist aber dennoch Unfug. Denn $i += 4; bedeutet schon: Nimm den aktuellen Wert von $i, zähle 4 dazu und schreibe ihn wieder nach $i zurück. Wenn du das nochmal in eine Zuweisung schreibst, also $i = ($i += 4); (die Klammern habe ich zur Verdeutlichung gesetzt), dann heißt das: Nimm den aktuellen Wert von $i, erhöhe ihn um 4, schreibe das Ergebnis wieder zurück, und dann weise das Ergebnis auch noch der Variablen $i zu. Du siehst, der letzte Schritt ist unnötig.

                              Wenn ich dieses ausführe, erhalte ich 2 Seiten, was eigentlich richtig ist?

                              Ja.

                              Wenn ich while($i < 6) in while($i < 12) ändere, erhalte ich 3 Seiten, scheint also richtig zu funktionieren!

                              Vermutlich, aber ich erkenne nicht, wie du dann die Grenze zwischen Seite 2 und 3 machst.

                              Sorry wenn ich vielleicht nerve, ...

                              Keine Sorge. Genervt bin ich höchstens, wenn ich nach zwei- oder dreimaligem Erklären den Eindruck bekomme, dass mein Gegenüber sich nicht einmal bemüht, mir zu folgen und mitzudenken. Den Eindruck habe ich aber bei dir nicht.

                              aber ich will es einfach verstehen und lernen.

                              Genau das ist für mich auch Motivation, dranzubleiben. Mir ist völlig klar, dass viele sich mit der trockenen technischen Materie schwer tun (auch wenn ich das manchmal vergesse), und dass manche etwas länger brauchen, bis sie es verstanden haben. Vielleicht auch andere Erklärungs-Ansätze brauchen, als ich es sonst gewöhnt bin. Insofern sind wir dat auf einem guten Weg, glaube ich.

                              Schönes Wochenende,
                               Martin

                              1. Hallo,

                                while($i < 6) // Warum $i<6?

                                die 6 ist derzeit ein statischer Wert. Ich möchte ja mit dieser Schleife die Seiten anlegen. In $SummeUserDBPDF steckt die Anzahl aller Einträge die ich auslesen möchte. In diesem Fall die 6.

                                Also dachte ich mir, 4 Einträge kommen auf die erste Seite, die restlichen kommen auf die zweite Seite bzw. auf die darauffolgende. Wenn ich den Wert auf 12 erhöhe, lautet es while($i < 12) sprich ich fange die Schleife bei 4 an deshalb vorhin auch die $i = 4 (die ersten Einträge sind ja für die erste Page reserviert).

                                Bei jedem Durchlauf prüfe ich, ist $i kleiner wie $SummeUserDBPDF wenn ja, hänge noch eine weitere Seite dran, wenn nicht, höre auf, denn die restlichen Einträge, die ja kleiner sind als 4 passen auf die Seite. Deshalb habe ich meine Schleife auch so geschrieben:

                                while($i < 6)
                                {
                                  echo "<page pageset=\"old\"></page>"; 
                                  $i = $i += 4 ;
                                } 
                                

                                4 sind im ersten Block, der ja immer da ist, derzeit ist $i = 4 sprich kleiner als 6 also hänge <page> noch einmal unten dran. Ein weiterer Durchlauf wird nicht passieren, denn unten zähle ich $i um 4 (4 weil auf die Page 4 Einträge platziert werden) nach oben, ab dann ist $i größer als 6.

                                Ich hoffe du verstehst was ich meine. Wir sind noch immer bei der Äußern Schleife. Einträge sind noch keine Vorhanden.

                                Der nächste Schritt wäre also, meine Ausgabe wie hier geschrieben etwas anzupassen. Meine Idee ist folgendes (und jetzt sind wir glaube ich bei dem Punkt was du meintest:

                                • Ich lege ein Zähler ganz oben an
                                • Bei jedem Durchlauf erhöhe ich ihn um eins
                                • Dieser Wert muss irgendwie hier mit eingebaut werden
                                <?php $pos = 1; 
                                                  foreach($UserAusgabe as $array)
                                          { ?>  
                                            <tr style="height:1.5em;">
                                              <td style="width:9%; text-align:left; vertical-align:top;"><?php echo $pos;?></td>
                                              <td style="width:89%; text-align:left; vertical-align:top;">
                                                <div style="padding-bottom:10px"><?php echo htmlspecialchars($array['UserName']); ?></div>
                                                <br><br>
                                              </td>
                                            </tr>
                                          <?php
                                          $pos++;
                                          } ?>    
                                

                                Ich denken dann hätte ich es geschafft. Die Frage ist nur, wie bringe ich dieses hier rein

                                foreach($UserAusgabe as $array)
                                
                                1. Hallo,

                                  sorry ich konnte mein Beitrag von gerade nicht mehr bearbeiten (die Zeit ist viel zu kurz)

                                  Eine Idee noch zum Auslesen der Datensätze

                                  Ich erweitere die Funktion füge dieser noch ein Start und Endlimit hinzu und kann die Einträge dann wie bei einer Pagination auslesen?

                                  Auf Seite ein wäre es 1 - 4 Auf Seite zwei 4 - 6 (für dieses Beispiel) usw...

                                  Könnte ich dieses so machen?

                                  1. Hallo,

                                    puhhh ich habe noch nicht aufgegeben und bin eigentlich zu 95% an meinem Ziel angekommen. Mein Code sieht nun so aus (was ich eben hinbekommen habe)

                                    <page backtop="1%" backbottom="2%" backleft="5%" backright="5%"> 
                                      <page_footer style="text-align:center; line-height:14px; font-size:10px; height:300px;">
                                        <p><?php echo nl2br(htmlspecialchars($SeitenUnten));?></p>
                                        <p>Seite [[page_cu]]/[[page_nb]]</p>
                                      </page_footer>
                                      <?php 
                                         $UserPDF = UserPDF($mysqli, $Bereich, 0, 4);
                                         $pos = 1; 
                                         
                                         foreach($UserPDF as $array) { ?> 
                                         
                                          <?php echo $pos;?> - <?php echo htmlspecialchars($array['UserPDF']); ?>
                                          <?php echo "<br>";?>
                                          
                                          <?php $pos++; } ?>  
                                    
                                    </page>
                                    
                                    <?php 
                                    $i = 4;
                                    while($i < $SummeUserDBPDF)
                                    { ?>
                                      
                                    <page pageset="old">
                                    <?php 
                                    $UserPDF = UserPDF($mysqli, $userCode, 4, 6); 
                                    foreach($UserPDF as $array) { ?> 
                                      
                                    <?php echo $pos;?> - <?php echo htmlspecialchars($array['UserPDF']); ?>
                                    <?php echo "<br>";?>
                                      
                                      <?php $pos++; } ?>  
                                    
                                    </page>
                                    
                                    <?php $i = $i += 4 ; } ?>
                                    

                                    Die Ausgabe sieht OK aus, wird auf Seiten aufgeteilt. Allerdings habe ich noch ein kleines Problem.

                                    1. Ich muss irgendwie die Zahlen $UserPDF = UserPDF($mysqli, $Bereich, 0, 4); dynamisch füllen. Der Gesamtwert steht in $SummeUserDBPDF
                                    1. Hallo,

                                      nach fast 24 Stunden und dank eurer Hilfe bin ich am Ziel angekommen, zumindest mit einer stark gekürzten Version. Tabellen sind noch keine drin, die folgende spätestens morgen.

                                      Hier meine Version

                                      <page backtop="1%" backbottom="2%" backleft="5%" backright="5%"> 
                                        <page_footer style="text-align:center; line-height:14px; font-size:10px; height:300px;">
                                          <p><?php echo nl2br(htmlspecialchars($SeitenUnten));?></p>
                                          <p>Seite [[page_cu]]/[[page_nb]]</p>
                                        </page_footer>
                                        <?php 
                                           $UserPDF = UserPDF($mysqli, $Bereich, 0, 4);
                                           $pos = 1; 
                                           
                                           foreach($UserPDF as $array) { ?> 
                                           
                                            <?php echo $pos;?> - <?php echo htmlspecialchars($array['UserPDF']); ?>
                                            <?php echo "<br>";?>
                                            
                                            <?php $pos++; } ?>  
                                      
                                      </page>
                                      
                                      <?php 
                                      $i = 4;
                                      $g = 4;
                                      $o = 5;
                                      
                                      while($i < $SummeUserDBPDF)
                                      { ?>
                                        
                                      <page pageset="old">
                                      <?php 
                                      $UserPDF = UserPDF($mysqli, $Bereich, $o, $g); 
                                      foreach($UserPDF as $array) { ?> 
                                        
                                      <?php echo $pos;?> - <?php echo htmlspecialchars($array['UserPDF']); ?>
                                      <?php echo "<br>";?>
                                        
                                        <?php $pos++; } ?>  
                                      
                                      </page>
                                      
                                      <?php 
                                      $i = $i += 4 ;  
                                      $g = 4+4;
                                      $o = 4+4;
                                      } 
                                      ?>
                                      
            2. Hallo

              die Daten kommen ja auch aus einer Datenbank.

              Dafür ist HTML2PDF aber nicht gedacht. Ich habe nicht gemeint die Daten aus einer Datenbank in HTML auszugeben und dann die HTML-Seite in PDF umzuwandeln. Sondern die Daten aus der Datenbank direkt in PDF auszugeben. Das kann HTML2PDF meiner Kenntnis nach aber nicht.

              Gruss

              MrMurphy

          2. @@MrMurphy1

            wie dedlfix bereits richtig geschrieben hat haben PDF und HTML/CSS nichts miteinander zu tun, außer dass die eventuell die gleichen Informationen enthalten sollen.

            Da haben wir ihn wohl unterschiedlich verstanden. Ich denke, er sagte, dass aus HTML/CSS durchaus PDF erzeugt werden kann.

            Das geht schon damit los, dass PDF ähnlich Papierformaten eine Größe hat, Webseiten jedoch nicht.

            Doch, eine (statische) Webseite hat zum Zeitpunkt des Renderns durchaus eine feste Größe, die sich aus der aktuellen Viewportgröße und dem Inhalt ergibt. (Bei Änderung der Viewportgröße wird die Seite neu gerendert.)

            Aus diesem Grund können nur sehr einfache HTML-/CSS-Seiten automatisch in PDF-Dateien umgewandelt werden.

            ?? Ich sehe keinen Grund, warum ein PDF-Generator nicht alles in PDF abbilden können sollte, was ein Browser auf den Bildschirm bringen kann (Bewegung von Inhalten ausgenommen).

            Wenn ein PDF-Generator mit weniger einfachen HTML-/CSS-Seiten nicht klarkommt, ist die Unzulänglichkeit in diesem Stück Software zu suchen, nicht im Konzept HTML/CSS in PDF zu wandeln.

            Deshalb ist es sinnvoller, die Informationen zunächst in einer Datenbank zu speichern und daraus dann die Ausgabeformate wie PDF, HTML oder auch andere zu erstellen.

            Oder einen PDF-Generator einzusetzen, der HTML/CSS versteht.

            LLAP 🖖

            --
            „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
            „Hat auf dem Forum herumgelungert …“
            (Wachen in Asterix 36: Der Papyrus des Cäsar)
            1. Tach!

              wie dedlfix bereits richtig geschrieben hat haben PDF und HTML/CSS nichts miteinander zu tun, außer dass die eventuell die gleichen Informationen enthalten sollen.

              Da haben wir ihn wohl unterschiedlich verstanden. Ich denke, er sagte, dass aus HTML/CSS durchaus PDF erzeugt werden kann.

              Mit Einschränkungen. Aber im Prinzip kann man aus jedem Format ein anderes erzeugen (solange das Zielformat die Eigenschaften prinzipiell unterstützt). Die Frage ist, wie umfangreich will man den Konverter gestalten?

              Das geht schon damit los, dass PDF ähnlich Papierformaten eine Größe hat, Webseiten jedoch nicht.

              Doch, eine (statische) Webseite hat zum Zeitpunkt des Renderns durchaus eine feste Größe, die sich aus der aktuellen Viewportgröße und dem Inhalt ergibt. (Bei Änderung der Viewportgröße wird die Seite neu gerendert.)

              Der Inhalt läuft aber auch gern mal über die Viewportgrenzen hinaus und kann dann mit Mitteln des Browser-UI in letzteren gebracht werden. Das geht mit Papier nicht. HTML ist also nicht an die Viewportgrenzen gebunden, der Inhalt auf dem Papier sollte es aber sein, sonst geht Information unerreichbar verloren. Und schon braucht man HTML/CSS, dass diese Forderung erfüllt, die es auf dem Schirm nicht unbedingt hätte erfüllen müssen.

              Aus diesem Grund können nur sehr einfache HTML-/CSS-Seiten automatisch in PDF-Dateien umgewandelt werden.

              ?? Ich sehe keinen Grund, warum ein PDF-Generator nicht alles in PDF abbilden können sollte, was ein Browser auf den Bildschirm bringen kann (Bewegung von Inhalten ausgenommen).

              Können kann man das mit Einschränkungen auf alle Fälle.

              Wenn ein PDF-Generator mit weniger einfachen HTML-/CSS-Seiten nicht klarkommt, ist die Unzulänglichkeit in diesem Stück Software zu suchen, nicht im Konzept HTML/CSS in PDF zu wandeln.

              Richtig, und das ist das Problem, das mit Aussagen zur Grundsätzlichkeit nicht zu lösen ist. Ein Browser hat jede Menge Manpower unter der Haube und eine sehr umfangreiche Rendering-Engine. Die Erwartungshaltung, dass dieser Umfang von einem Projekt mit (anzunehmenderweise) deutlich weniger Ressourcen abgebildet werden kann, würde ich nicht haben und auch nicht aufzubauen versuchen.

              Deshalb ist es sinnvoller, die Informationen zunächst in einer Datenbank zu speichern und daraus dann die Ausgabeformate wie PDF, HTML oder auch andere zu erstellen.

              Oder einen PDF-Generator einzusetzen, der HTML/CSS versteht.

              Dann nenn mal einen!

              dedlfix.

              1. @@dedlfix

                Der Inhalt läuft aber auch gern mal über die Viewportgrenzen hinaus und kann dann mit Mitteln des Browser-UI in letzteren gebracht werden. Das geht mit Papier nicht. HTML ist also nicht an die Viewportgrenzen gebunden, der Inhalt auf dem Papier sollte es aber sein, sonst geht Information unerreichbar verloren. Und schon braucht man HTML/CSS, dass diese Forderung erfüllt, die es auf dem Schirm nicht unbedingt hätte erfüllen müssen.

                Im PDF ist das zu sehen, was auf dem Bildschirm (bei adäquater Viewportgröße) initial ohne Nutzeraktion auch zu sehen ist. Dass die Informationen innerhalb des (PDF-)Viewports liegen, liegt in der Verantwortung des CSS-Entwicklers.

                Oder einen PDF-Generator einzusetzen, der HTML/CSS versteht.

                Dann nenn mal einen!

                Keine Ahnung, gibt es denn einen? Vieleicht müsste der erst geschrieben werden. Und vielleicht wird der niemals geschrieben, weil der Aufwand (Kosten) in keinem Verhältnis zum Nutzen (Gewinn) steht.

                Kann XSL hier weiterhelfen (polyglottes HTML vorausgesetzt)?

                LLAP 🖖

                --
                „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
                „Hat auf dem Forum herumgelungert …“
                (Wachen in Asterix 36: Der Papyrus des Cäsar)
                1. Tach!

                  Im PDF ist das zu sehen, was auf dem Bildschirm (bei adäquater Viewportgröße) initial ohne Nutzeraktion auch zu sehen ist.

                  Nein, da spielt noch responsive mit rein. Was auf dem einen Bildschirm zu sehen ist, muss noch lange nicht auf dem anderen zu sehen sein. Papier hat eine festgelegte Größe, was der Bildschirm anzeigt hat damit nur bedingt was zu tun.

                  dedlfix.

                  1. @@dedlfix

                    Im PDF ist das zu sehen, was auf dem Bildschirm (bei adäquater Viewportgröße) initial ohne Nutzeraktion auch zu sehen ist.

                    Nein, da spielt noch responsive mit rein.

                    ?? Wie sollte?

                    Was auf dem einen Bildschirm zu sehen ist, muss noch lange nicht auf dem anderen zu sehen sein. Papier hat eine festgelegte Größe

                    Wie ich sagte: der Bildschirm/Viewport auch – zum Zeitpunkt des Renderns.

                    LLAP 🖖

                    --
                    „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
                    „Hat auf dem Forum herumgelungert …“
                    (Wachen in Asterix 36: Der Papyrus des Cäsar)
                    1. Tach!

                      Im PDF ist das zu sehen, was auf dem Bildschirm (bei adäquater Viewportgröße) initial ohne Nutzeraktion auch zu sehen ist.

                      Nein, da spielt noch responsive mit rein.

                      ?? Wie sollte?

                      Ich hatte "bei adäquater Viewportgröße" überlesen. Wie definierst du die denn? Schreibst du das HTML mit cm als Größenangaben, damit es auf beiden Medien adäquat vergleichbar ist?

                      dedlfix.

                      1. @@dedlfix

                        Nein, da spielt noch responsive mit rein.

                        ?? Wie sollte?

                        Anders (besser) gesagt: !! Ja, unbedingt.

                        Ich hatte "bei adäquater Viewportgröße" überlesen. Wie definierst du die denn?

                        Gar nicht. Der Inhalt passt sich der Viewportgröße an. Bei Bildschirmausgabe dem Viewport des Browsers, bei PDF-Generierung der Größe des virtuellen Papiers (abzüglich Seitenränder). Responsive eben. Device-agnostic.

                        Schreibst du das HTML mit cm als Größenangaben,

                        Das (oder pt, …) könnte man in Stylesheet für @media print tatsächlich tun, wenn man sich nicht auf irgendeinen aus der Luft gegriffenen Umrechnungsfaktor verlassen möchte.

                        damit es auf beiden Medien adäquat vergleichbar ist?

                        Vergleichbar in welchem Sinne?

                        LLAP 🖖

                        --
                        „Wir haben deinen numidischen Schreiber aufgegriffen, o Syndicus.“
                        „Hat auf dem Forum herumgelungert …“
                        (Wachen in Asterix 36: Der Papyrus des Cäsar)
                        1. Tach!

                          Schreibst du das HTML mit cm als Größenangaben,

                          Das (oder pt, …) könnte man in Stylesheet für @media print tatsächlich tun, wenn man sich nicht auf irgendeinen aus der Luft gegriffenen Umrechnungsfaktor verlassen möchte.

                          damit es auf beiden Medien adäquat vergleichbar ist?

                          Vergleichbar in welchem Sinne?

                          Vermutlich muss das nicht vergleichbar sein. Das ist ja grade der Punkt, an dem es hapert.

                          Es geht darum, ein HTML/CSS zu erzeugen, das auf Papier eine gute Figur hinlegt. Ideal wäre, wenn man daselbe HTML für beides nehmen könnte. Kann man aber nicht, weil die Werkzeuge es nicht hergeben. Oder du beschränkst das HTML generell auf die gemeinsame Basis. Das wird nicht ohne Verzicht auf aktuelle Elemente für den Bildschirm einhergehen, was man eigentlich nicht will. Genausowenig wie HTML für Mail-Clients dasselbe wie für den Bildschirm sein wird, weil dort absichtlich nur wenig unterstützt wird. Theoretisch kann man sich das alles idealreden, bringt nur nichts. Für mich bleibt es dabei, dass Daten nach PDF zu bringen über den Umweg HTML/CSS praktisch nicht uneingeschränkt empfehlenswert ist.

                          dedlfix.

                          1. Hallo

                            Vermutlich muss das nicht vergleichbar sein. Das ist ja grade der Punkt, an dem es hapert.

                            Es geht darum, ein HTML/CSS zu erzeugen, das auf Papier eine gute Figur hinlegt. Ideal wäre, wenn man daselbe HTML für beides nehmen könnte. Kann man aber nicht, weil die Werkzeuge es nicht hergeben. Oder du beschränkst das HTML generell auf die gemeinsame Basis. Das wird nicht ohne Verzicht auf aktuelle Elemente für den Bildschirm einhergehen, was man eigentlich nicht will.

                            Worum geht es denn hier?

                            Sara will mit PHP, also auf dem Server, aus einem HTML-Dokument ein PDF generieren. Ob das der ideale Weg ist, sei mal dahingestellt. Man hat zumindest den Vorteil, per HTML und CSS mit einem selbst bekannten Methoden den Inhalt des Dokuments anzuordnen und zu stylen.

                            Ein für den PDF-Export geeignetes und den Maßgaben von Papierformaten folgendes HTML-Gerüst auf dem Server zu generieren und dann erfolgreich nach PDF umzurechnen, sollte ja grundsätzlich kein Problem sein. Das HTML-Dokument kann ja auf den PDF-Export optimiert werden. Mit dem Dokument, das an Browser und Suchmaschinen ausgeliefert wird, braucht es ja nicht mehr als den Inhalt oder Teile des Inhalts gemein haben.

                            Martin hat mit Pseudocode ja schon beschrieben, wie die Tabellen, an denen es bei Sara offensichtlich scheitert, so geteilt werden können, dass sie nicht über ein Seitenende hinausragen. Den Inhalt entsprechend des Requests aus der Datenbank zu holen und in das (ausschließlich) zum PDF-Export geeignete HTML-Gerüst zu stecken, das nach dem erfolgreichen Export verworfen wird, ist Saras Aufgabe.

                            Tschö, Auge

                            --
                            Es schimmerte ein Licht am Ende des Tunnels und es stammte von einem Flammenwerfer.
                            Terry Pratchett, „Gevatter Tod“
            2. ?? Ich sehe keinen Grund, warum ein PDF-Generator nicht alles in PDF abbilden können sollte, was ein Browser auf den Bildschirm bringen kann (Bewegung von Inhalten ausgenommen).

              Mit Canvas kann man auch nicht bewegte Inhalte generieren. Das ist eine ziemlich überflüssige Diskussion.

  3. Hej Sara,

    HTML zu PDF

    Vielleicht kann man Dein problem ja ganz anders angehen. Ich weiß ja nicht viel über Deine Anwendung, aber ich habe mal für eine Website ein Print-CSS geschrieben, das extrem umfangreich war.

    Auf allen Betriebssystemen kann man die Druckvariante statt zu drucken auch als PDF speichern (ggfs mit PlugIn).

    Für meinen damaligen Fall war das okay, allerdings ist es ätzend ein umfangreiches Print-CSS zu schreiben...

    Gruß,

    Marc

  4. Huhuh.

    Ich darf dann mal auflösen. Wie der ganze Faden schon erläutert, es gibt und wird kein "eigenes" Tool geben, was die Erwartungshaltung gänzlich erfüllt. Einzig ausgewachsene Browser können gegebenes HTML/CSS adäquat rendern. Genau das muss man nutzen, um zum Ergebnis zu kommen:

    http://phantomjs.org/

    http://wkhtmltopdf.org/

    EDIT: Ups, 1unitedpower war schneller.