web-dev-qa-db-ja.com

wkhtmltopdfのテーブル行内で改ページを回避する方法

1つのテーブルでhtmlページからpdfレポートを生成しています。

目的でwkhtmltopdfを使用しています。

pdfが生成されると、-trタグの任意の場所で中断します

避けたいです。

70

2015年9月9日更新:使用しているバージョンを確認してください: wkhtmltopdf 0.12.2.4は問題を修正すると言われています(チェックしていません)


これはwkhtmltopdfの既知の問題です。 Webkitで使用される改ページアルゴリズム(WKhtmltopdfのWK)は、大きなテーブルでは実際にはうまく機能しません。テーブルをより簡単にページに分割できる小さなチャンクに分割し、cssを頻繁に使用することをお勧めします。

table, tr, td, th, tbody, thead, tfoot {
    page-break-inside: avoid !important;
}

また、次のwkhtmltopdfの問題もご覧ください。たとえば、テーブル分割の問題について議論する興味深いコメントがあります。あなたに役立つかもしれない168のテーブルをプログラムで分割するJSソリューションがあります(私はそれを使用しません)。

2013年8月11日更新これについては、上記リンクの問題168で多くの議論があります。誰かがより良いテーブル分割をサポートするwkhtmltopdfのバージョンをコンパイルすることができましたが、残念ながら公式にはリリースされておらず、他のバグが含まれているようです。私はそれを取得する方法がわからず、Windowsでコンパイルする方法もわかりませんが、興味のある人は誰でもたとえばコメントを確認できます ここ (下記の新しいアップデートをご覧ください)。

2014年2月24日更新wkhtmltopdf 0.12では、この機能が大幅に改善されたことを喜ばしく思います。ただし、0.12.1を待って、新しいバージョンの使用を開始する前に十分にテストしてください。アンチアライズで作業している新しい人たちは素晴らしい仕事をしています(アシュクルツロックス)! wkhtmltopdf.org および github で更新してください。 Googleコードサイトは廃止され、徐々に移行されています。

128
Nenotlep

それは古い投稿ですが、適切な解決策を見つけるために多くの時間を無駄にしていたので、ここにそれを置きます。誰かに役立つかもしれません。

だから私が読んだことから、問題は

page-break-inside: avoid

動作しないということです。しかし実際には、display:blockを持つ要素に設定すると、期待どおりに動作します(SOのどこかに記載されています)。したがって、テーブルcssの単純な構造の場合

td div, th div{
    page-break-inside: avoid;
}

およびテーブル構造

<table>
....
<tr>
    <td><div>some text</div></td>
    <td><div>more text</div></td>
</tr>
....
</table>

期待どおりに動作します。

私はもう少し複雑な行幅の場合があったので、上からの解決策はそれを和らげることでしたが、これは望ましい効果ではありませんでした。行スパンの行セットごとにdivを使用して解決しました。私のjquery jsはすべての仕事をしています:

$(window).load(function () {
    var sizes = {};
    $('#the_table tr:first th').each(function (a, td) {         
        var w = $(td).width();
        if (sizes.hasOwnProperty('' + a)) {
            if (sizes['' + a] < w)
                sizes['' + a] = w;
        }
        else {
            sizes['' + a] = w;
        }
    });

    var tableClone = $('#the_table').clone();
    $('#the_table').replaceWith('<div class="container"></div>');

    var curentDivTable;
    var cDiv = $('.container');
    tableClone.find('tr').each(function (i, ln) {
        var line = $(ln);
        if (line.hasClass('main_row')) {
            var div = $('<div class="new-section"><table><tbody>')
            currentDivTable = div.find('tbody');
            cDiv.append(div);               
        }
        currentDivTable.append(line);
    });
    //optional - maybe in % its better than px
    var sum = 0;
    $.each(sizes, function (a, b) {
        sum += b;
    });
    var widths = {};
    $.each(sizes, function (a, b) {
        var p = Math.ceil(b * 100 / sum);
        widths['' + a] = p + '%';
    });
    //setup
    $('.container table').each(function (a, tbl) {
        $(tbl).find('tr:first td, tr:first th').each(function (b, td) {
            $(td).width(widths['' + b]);
        });
        $(tbl).addClass('fixed');
    });
});

css:

div.new-section {
    page-break-inside: avoid;
}
.container, .new-section, .new-section table.fixed{
    width: 100%;
}

.new-section table.fixed{
    table-layout:fixed;
}

すべてが必要かどうかはわかりませんし、完璧だとは思いませんが、仕事はします。 chromeのみでテスト済み

17

0.12以降、この問題は解決されましたが、テーブルが長すぎてページに収まらない場合、wkhtmltopdfは2つの部分に分割し、新しいページで列ヘッダーを繰り返します。これらの列ヘッダーは最初の行に重ねて表示されます。

Wkhtmltopdf github issuesセクションでこの問題の一時的な解決策を見つけました: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2531

ビューcssに次の行を追加するだけです。

tr {
  page-break-inside: avoid; 
}
13
Nacho Moço

Wkhtmltopdf 0.12.2.1以降でこの問題が修正されたことがわかりました。

6
York Mak

何らかの理由で私の特定のケースでは、以前の答えのどれも私のために機能しませんでした。最終的に機能したのは、実際にはいくつかのことの組み合わせでした。

  1. (Ubuntu 16.04に)インストールしました pdfkitというWkhtmltopdf pythonラッパー pip3を使用し、次にapt-getでWkhtmltopdfをインストールする代わりに以下のスクリプトに従って静的バイナリ(バージョン0.12.3)、 ここから取得

    #!/bin/sh
    
    Sudo apt-get install -y openssl build-essential xorg libssl-dev
    wget http://download.gna.org/wkhtmltopdf/0.12/0.12.3/wkhtmltox-0.12.3_linux-generic-AMD64.tar.xz
    tar -xJf wkhtmltox-0.12.3_linux-generic-AMD64.tar.xz
    cd wkhtmltox
    Sudo chown root:root bin/wkhtmltopdf
    Sudo cp -r * /usr/
    
  2. このCSSを追加しました(回答の1つで提案されています)。

    tr, td div, th div{
        page-break-inside: avoid;
    }
    
  3. そして、alsoここでも提案されているように<thead>および<tbody>タグを追加します(これらがなければ、テーブルはtheいままになります)仕方):

    <table>
        <thead>
            <tr>
                <th>Column 1</th>
                <th>Column 2</th>
            </tr>
        </thead>
    
        <tbody>
            <tr>
                <td>Value 1</td>
                <td>Value 2</td>
            </tr>
        </tbody>
    </table>
    

これらの変更により、 Makoテンプレート を使用してHTMLを生成し、それをWkhtmltopdfにフィードして、美しくページ付けされたPDFを取得できます:)

5
Acapulco

テーブルに対してあらゆる方法で操作を試みましたが、行の中央に改ページが挿入されるのを止めることはできませんでした。必死になって、さまざまなバージョンを試しましたが、次のことがわかりました。

Wkhtmltopdf 0.12.2.1:悪い

Wkhtmltopdf 0.12.3:悪い

Wkhtmltopdf 0.12.1:良い

私の解決策はバージョン0.12.1にダウングレードすることで、これで問題が解決しました。確かに、彼らは私のHTMLについてスーパーOCDでなかったためかもしれませんが、HTMLはTinyMCE内で(ユーザーによって)生成されるため、あまり選択肢がありません。

また、ネストされたテーブルはどのバージョンでも機能しません。

3
Ben Hitchcock

私は何日もこの問題を掘り下げて、最終的に完璧な解決策を見つけました。このプロジェクトを参照できます phpwkhtmltopdf 。ディレクトリarticleを調べると、3つの問題に対する3つの解決策が見つかります。要するに、究極の解決策はCSSスタイルを追加することです

thead {
    display: table-row-group;
}
tr {
    page-break-before: always;
    page-break-after: always;
    page-break-inside: avoid;
}
table {
    Word-wrap: break-Word;
}
table td {
    Word-break: break-all;
}

中国人の方は、このサイトを自由にチェックしてください 関連についてwkhtmltopdf、你一定想知道これら 必要に応じて要点を確認してください wkhtmltopdfの要点

2
UnixAgain

trを中断せずにpdf内で改ページを使用する方法

これは、任意のhtmlファイルで使用できる解決策です。

Trを開始した後、tr内のdivを取得し、このcssをdivに渡す必要があります。

<tr>
      <div style="page-break-inside:avoid !important; page-break-after:auto !important; overflow: hidden; display:block !important; width:100% ">
     </tr>
2
Vibha Kachhela

私はこのCSSが問題を解決した試行錯誤の多くの後、同じ問題の追加に直面していました

tr { display: inline-table; }

まだこれに問題がある人にとって、覚えておくべきことの1つは、tablebodyの直接の子でなければならないということです。私に何が起こったのか。

1
Luccas Correa

テーブルヘッドはありますか?テーブル本体?

<table>
<tbody>
<tr><th>Name</th><th>Value</th></tr>
<tr><td>url</td><td>stackoverflow.com</td></tr>
<tr><td>ip</td><td>123.123.123.123</td></tr>
</tbody>
</table>

それはテーブルの適切なフォーマットです、ほとんどのブラウザはそれほど気にすることはできませんでしたが、convertersあなたが言及したもののように、欠落している<tbody>または<th>タグがあればそれらを最初に追加してみてください。

1
suicidal.banana

Nanotelepが述べたことに加えて、手動のテーブル改ページアルゴリズムの実用的な実装があります。 https://github.com/AAverin/JSUtils/tree/master/wkhtmltopdfTableSplitHack

1
AAverin

上記の答えはうまくいきませんでした。 pdfkit configのズームオプションを特に無効にする必要がありました。

PDFKit.configure do |config|

  config.default_options = {
    print_media_type: false,
    page_size: "A4",
    encoding: "UTF-8",
    ## Make sure the zoom option is not enabled!
    ## zoom: '1.3',
    disable_smart_shrinking: false,
    footer_right: "Page [page] of [toPage]"
  }

end
1
Hendrik

別のオプション:各trを独自のtbodyに配置してから、tbodyにpeage break cssルールを適用します。テーブルは複数のtbodysをサポートします。

少し余分なマークアップですが、私にとってはうまく機能します。

1
Troy Morehouse

最新の h4cc/wkhtmltopdf-AMD64バージョン0.12.4 を使用して、この問題に苦労しました。最後に、パッケージのバージョンを0.12.3にダウングレードして機能させました。

1
emix

いくつかの提案されたソリューションの組み合わせを使用して問題を解決しました。

テーブルをdivでラップし、次のCSSを定義しました。

.wrapping-div {
        display: block;
        page-break-inside: avoid !important;
    }

.wrapping-div table, .wrapping-div tbody, .wrapping-div tr, .wrapping-div td, .wrapping-div th {
        page-break-inside: avoid !important;
    }

終了時のテーブル構造は、次の例のように定義されました。

<div class="wrapping-div">
 <table>
  <tbody>
   <tr>
    <th>
      header
    </th>
    <td>
      content
    </td>
   </tr>
  </tbody>
 </table>
</div>

Tdまたはthタグ内にdivを作成する必要はありませんでした。

問題を解決しようとしたときに気づいた重要なこと:

  • Tbodyはテーブルに含まれている必要があります
  • Divにはdisplay:blockが必要です
  • テーブルがページに収まらない場合、テーブル全体が自動的に次のページに移動します(これを巨大なテーブルで試したことはありません)
  • CSSから"。wrapping-div table"セレクターのみを削除すると、テーブルを2ページに分割できますが、2ページの1つのセルを壊さずに正しくレンダリングします( Wordのデフォルトの動作に似ています)

これがお役に立てば幸いです。

1
Tiago Freitas

私はこのばかげた解決策を見つけましたが、それは非常にうまくいきました私にとっては:)

このように非常に長い行スパン列を配置します

<td rowspan="XXX TOTAL ROWS" style="width:0px"></td>

そして、テーブルは壊れません。

1
aswzen

改ページを避けるために、cssオプションを使用して改ページを使用できます。

tr { page-break-inside: avoid; }

コンテンツを壊します(Image/Text)そしてそれを次のページに表示させます

.sample-image { page-break-before: always; }
0
Arvind singh