wake-up-neo.com

Wie mache ich die Seitennummerierung in Header/Footer-HTMLs mit wkhtmltopdf?

Ich entwickle ein elektronisches Rechnungssystem, und eine unserer Funktionen ist das Generieren von PDFs der Rechnungen und deren Versendung. Wir haben mehrere Vorlagen für Rechnungen und werden später weitere erstellen. Daher haben wir uns entschieden, HTML-Vorlagen zu verwenden, ein HTML-Dokument zu generieren und es dann in PDF zu konvertieren. Wir haben jedoch ein Problem mit wkhtmltopdf. Soweit ich weiß (ich habe seit Tagen nach Google gesucht, um die Lösung zu finden), können wir nicht einfach HTML als Kopf-/Fußzeile verwenden und Seitennummern darin anzeigen.

In einem Fehlerbericht (oder so) ( http://code.google.com/p/wkhtmltopdf/issues/detail?id=140 ) habe ich gelesen, dass mit JavaScript diese Kombination möglich ist. Auf dieser Seite oder anderswo finden Sie jedoch keine weiteren Informationen dazu.

Es ist natürlich nicht so wichtig, die Verwendung von JavaScript zu erzwingen. Wenn mit wkhtmltopdf CSS-Zauber funktionieren könnte, wäre dies genauso großartig wie jede andere hackish-Lösung.

Vielen Dank!

39
Tamás Barta

Um die Seitennummer und die Gesamtseiten anzuzeigen, können Sie dieses Javascript-Snippet in Ihrer Fußzeile oder im Header-Code verwenden:

  var pdfInfo = {};
  var x = document.location.search.substring(1).split('&');
  for (var i in x) { var z = x[i].split('=',2); pdfInfo[z[0]] = unescape(z[1]); }
  function getPdfInfo() {
    var page = pdfInfo.page || 1;
    var pageCount = pdfInfo.topage || 1;
    document.getElementById('pdfkit_page_current').textContent = page;
    document.getElementById('pdfkit_page_count').textContent = pageCount;
  }

Und rufen Sie getPdfInfo mit page onload auf

Natürlich werden pdfkit_page_current und pdfkit_page_count die beiden Elemente sein, die die Zahlen zeigen.

Ausschnitt aus hier

21
Dan Mazzini

Eigentlich ist es viel einfacher als mit dem Code-Snippet. Sie können das folgende Argument in die Befehlszeile einfügen: --footer-center [page]/[topage].

Wie bereits erwähnt, befinden sich weitere Variablen im Abschnitt Fußzeilen und Kopfzeilen von der Dokumentation .

60
makro

Neben einigen anderen Parametern werden die Seitennummer und die Gesamtseitennummer als Abfrageparameter an die Fußzeile HTML übergeben, wie in den offiziellen Dokumenten beschrieben:

Die Argumente [Seitennummer] werden auf GET-Art an die Header-/Footer-HTML-Dokumente gesendet.

Quelle: http://wkhtmltopdf.org/usage/wkhtmltopdf.txt

Die Lösung besteht also darin, diese Parameter mit etwas JS abzurufen und in die HTML-Vorlage zu rendern. Hier ist ein vollständiges Arbeitsbeispiel für eine HTML-Fußzeile:

<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <script>
        function substitutePdfVariables() {

            function getParameterByName(name) {
                var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
                return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
            }

            function substitute(name) {
                var value = getParameterByName(name);
                var elements = document.getElementsByClassName(name);

                for (var i = 0; elements && i < elements.length; i++) {
                    elements[i].textContent = value;
                }
            }

            ['frompage', 'topage', 'page', 'webpage', 'section', 'subsection', 'subsubsection']
                .forEach(function(param) {
                    substitute(param);
                });
        }
    </script>
</head>
<body onload="substitutePdfVariables()">
    <p>Page <span class="page"></span> of <span class="topage"></span></p>
</body>
</html>

substitutePdfVariables() wird im body onload aufgerufen. Wir erhalten dann jede unterstützte Variable aus der Abfragezeichenfolge und ersetzen den Inhalt in allen Elementen durch einen entsprechenden Klassennamen.

30
theDmi

Aus der wkhtmltopdf-Dokumentation ( http://madalgo.au.dk/~jakobt/wkhtmltoxdoc/wkhtmltopdf-0.9.9-doc.html ) unter der Überschrift "Fußzeilen und Kopfzeilen" befindet sich ein zu erreichender Code-Ausschnitt Nummerierung:

<html><head><script>
function subst() {
  var vars={};
  var x=document.location.search.substring(1).split('&');
  for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);}
  var x=['frompage','topage','page','webpage','section','subsection','subsubsection'];
  for(var i in x) {
    var y = document.getElementsByClassName(x[i]);
    for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]];
  }
}
</script></head><body style="border:0; margin: 0;" onload="subst()">
<table style="border-bottom: 1px solid black; width: 100%">
  <tr>
    <td class="section"></td>
    <td style="text-align:right">
      Page <span class="page"></span> of <span class="topage"></span>
    </td>
  </tr>
</table>
</body></html>

Es gibt auch mehr verfügbare Variablen, die anstelle von Seitennummern zur Verwendung in Kopf-/Fußzeilen verwendet werden können.

14

Die Art und Weise, in der dies geschehen sollte (dh, wenn wkhtmltopdf dies unterstützte), würde das richtige CSS Paged Media verwenden: http://www.w3.org/TR/css3-gcpm/

Ich schaue, was es jetzt braucht.

1
rainabba

Sicherer Ansatz, auch wenn Sie XHTML verwenden (z. B. mit Thymeleaf). Der einzige Unterschied zu anderen Lösungen ist die Verwendung von /Tags.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"/>
    <script>
        /*<![CDATA[*/
        function subst() {
            var vars = {};
            var query_strings_from_url = document.location.search.substring(1).split('&');
            for (var query_string in query_strings_from_url) {
                if (query_strings_from_url.hasOwnProperty(query_string)) {
                    var temp_var = query_strings_from_url[query_string].split('=', 2);
                    vars[temp_var[0]] = decodeURI(temp_var[1]);
                }
            }
            var css_selector_classes = ['page', 'topage'];
            for (var css_class in css_selector_classes) {
                if (css_selector_classes.hasOwnProperty(css_class)) {
                    var element = document.getElementsByClassName(css_selector_classes[css_class]);
                    for (var j = 0; j < element.length; ++j) {
                        element[j].textContent = vars[css_selector_classes[css_class]];
                    }
                }
            }
        }
        /*]]>*/
    </script>
</head>
<body onload="subst()">
    <div class="page-counter">Page <span class="page"></span> of <span class="topage"></span></div>
</body>

/ - Letzter Hinweis: Wenn Sie Thymeleaf verwenden, ersetzen Sie <script> durch <script th:inline="javascript">.

1
Juangui Jordán