web-dev-qa-db-ja.com

wkhtmltopdfを使用してヘッダー/フッターHTMLでページ番号を付ける方法

私は電子請求システムを開発していますが、私たちの機能の1つは請求書のPDFを生成し、それらを郵送することです。請求書には複数のテンプレートがあり、後で作成するため、HTMLテンプレートを使用してHTMLドキュメントを生成し、それをPDFに変換することにしました。しかし、wkhtmltopdfの問題に直面しています。私が知る限り(解決策を見つけるために何日もGoogleで調べてきました)、HTMLをヘッダー/フッターとして使用することも、ページ番号を表示することもできません。

バグレポート(またはそのような)( http://code.google.com/p/wkhtmltopdf/issues/detail?id=14 )では、JavaScriptを使用してこのコンボを達成できることを読みました。しかし、それを行う方法に関する他の情報は、このページまたは他の場所で見つけることができません。

もちろん、JavaScriptを強制的に使用することはそれほど重要ではありません。wkhtmltopdfでCSSマジックが機能する場合、他のハッキングソリューションと同じくらい素晴らしいでしょう。

ありがとう!

47
Tamás Barta

ページ番号と合計ページを表示するには、フッターまたはヘッダーコードで次のJavaScriptスニペットを使用できます。

  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;
  }

ページonloadでgetPdfInfoを呼び出します

もちろん、pdfkit_page_currentとpdfkit_page_countは、数値を示す2つの要素になります。

here から取得したスニペット

27
Dan Mazzini

実際には、コードスニペットよりもはるかに簡単です。コマンドラインで次の引数を追加できます。--footer-center [page]/[topage]

前述のリチャードと同様に、他の変数は ドキュメント のFooters and Headersセクションにあります。

68
makro

他のいくつかのパラメーターのうち、ページ番号と総ページ番号は、公式ドキュメントに概説されているように、クエリparamsとしてフッターHTMLに渡されます。

... [ページ番号]引数は、GET形式でヘッダー/フッターhtmlドキュメントに送信されます。

ソース: http://wkhtmltopdf.org/usage/wkhtmltopdf.txt

そのため、ソリューションは、少しのJSを使用してこれらのパラメーターを取得し、HTMLテンプレートにレンダリングすることです。次に、フッターHTMLの完全な動作例を示します。

_<!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()はbody onloadで呼び出されます。次に、クエリ文字列からサポートされている各変数を取得し、すべての要素のコンテンツを一致するクラス名に置き換えます。

34
theDmi

Wkhtmltopdfのドキュメント( http://madalgo.au.dk/~jakobt/wkhtmltoxdoc/wkhtmltopdf-0.9.9-doc.html )の見出し「Footers and Headers」の下にコードスニペットがありますページ番号を付けるには:

<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>

また、ヘッダー/フッターで使用するページ番号以外の代替可能な変数もあります。

16

それが行われるべきである方法(つまり、wkhtmltopdfがそれをサポートした場合)は、適切なCSS Paged Mediaを使用します: http://www.w3.org/TR/css3-gcpm/

私はそれが今何をするかを調べています。

1
rainabba

XHTML(thymeleafなど)を使用している場合でも、安全なアプローチ。他のソリューションとの唯一の違いは、//タグの使用です。

<!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>

最後のメモ: thymeleafを使用している場合は、<script> with <script th:inline="javascript">

1
Juangui Jordán