如何避免wkhtmltopdf表格行内的分页符

时间:2012-11-22 16:11:37

标签: wkhtmltopdf pdfkit

我正在使用一个表从html页面生成pdf报告。

我正在使用 wkhtmltopdf

生成pdf时,会破坏tr标记中的任何位置

我想避免它。

19 个答案:

答案 0 :(得分:127)

更新2015年9月17日:检查您使用的版本:wkhtmltopdf 0.12.2.4 is said to fix the problem (I have not checked)


这是wkhtmltopdf中的一个已知问题。 webkit使用的分页算法(WK在WKhtmltopdf中)对于大型表格并不适用。我建议将表拆分为较小的块,这些块更容易拆分为页面并使用css:

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

另外看看下面的wkhtmltopdf问题,他们有一些有趣的评论,例如讨论表分裂问题。有一个JS解决方案,以编程方式在168中拆分可能对您有用的表(尽管我不使用它)。

更新08.11.2013 在上面链接的问题168中有很多关于此的讨论。有人设法编译了一个支持更好的表格破坏的wkhtmltopdf版本,但不幸的是它似乎没有正式发布,可能包含其他错误。我不知道如何获得它,我不知道如何在Windows上编译,但任何有兴趣的人都可以查看评论 here (见下面的新更新)。 / p>

更新24.02.2014 你会很高兴听到在wkhtmltopdf 0.12中这个功能已经大大改进了。然而,在开始使用任何新版本之前等待0.12.1并进行彻底测试,虽然使用antialize的新人做得很好(ashkulz rock),但它仍然有点不稳定!随时更新wkhtmltopdf.orggithub。谷歌代码网站已经过时,正在慢慢迁移。

答案 1 :(得分:16)

这是老帖子,但由于我浪费了很多时间试图找到合适的解决方案,我会把它放在这里,也许它会对某人有用。

所以从我读到的,

的问题
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>

将按预期工作。

我有更复杂的案例与rowpans,所以上面的解决方案是打破和平,这是不希望的效果。我使用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;
}

我不知道是否需要一切,我不认为它是完美的,但它确实起到了作用。仅在镀铬上测试

答案 2 :(得分:13)

自0.12以来,这个问题已经解决了,但有时候,当一个表太长而无法放入页面时,wkhtmltopdf将它分成两部分并重复新页面上的列标题,这些列标题显示为叠加到第一个行。

我在wkhtmltopdf github问题部分找到了这个问题的暂时解决方案: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2531

只需将此行添加到您的视图css:

tr {
  page-break-inside: avoid; 
}

答案 3 :(得分:6)

我发现wkhtmltopdf 0.12.2.1以后修复了这个问题。

答案 4 :(得分:5)

在我的特殊情况下由于某些原因,以前的答案都没有对我有用。最终工作的实际上是几件事的组合。

  1. 我使用pip3安装(在Ubuntu 16.04中)the Wkhtmltopdf python wrapper called pdfkit,然后而不是通过apt-get安装Wkhtmltopdf我按照下面的脚本安装了静态二进制文件(版本0.12.3) ,taken from here

    #!/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(如其中一个答案所示):

    tr, td div, th div{
        page-break-inside: avoid;
    }
    
  3. 然后添加<thead><tbody>标签也是如此(如果没有这些,表格仍会以丑陋的方式破坏):

    <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>
    
  4. 通过这些修改,我现在可以成功使用Mako templates生成HTML,然后将其提供给Wkhtmltopdf并获得精美的分页PDF:)

答案 5 :(得分:3)

我尝试了对表格进行各种操作,但我尝试过的任何操作都无法阻止页面中断被放入中间行。 无奈之下,我尝试了不同的版本,并发现了以下内容:

Wkhtmltopdf 0.12.2.1:错误

Wkhtmltopdf 0.12.3:错误

Wkhtmltopdf 0.12.1:好

我的解决方案是降级到版本0.12.1,这解决了我的问题。当然,他们可能部分原因在于我的html并不是超级强迫症,但由于HTML是在TinyMCE内部生成的(用户),我真的没有多少选择。

此外,嵌套表格不适用于任何版本。

答案 6 :(得分:2)

如何在不破坏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>

答案 7 :(得分:1)

另一种选择:将每个tr放入其自己的tbody中,然后将peage break css规则应用于tbody。表支持多个tbody s。

一些额外的标记,但对我来说效果不错。

答案 8 :(得分:1)

我在这个问题上苦苦挣扎,使用最新的h4cc/wkhtmltopdf-amd64 version 0.12.4,最后通过将软件包的版本降级为0.12.3使它正常工作!

答案 9 :(得分:1)

我结合了一些建议的解决方案来解决了这个问题。

我将表格包装在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。

我在尝试解决问题时注意到的重要事项:

  • 表中必须包含躯干
  • div必须具有显示:块
  • 当表格不适合页面使用时,它将自动将整个表格移至下一页(我还没有尝试使用大表格进行此操作)
  • 如果仅从CSS中删除“。wrapping-div表” 选择器,它将允许将该表拆分为两页,但是将正确呈现该表,而不会破坏其中的一个单元格。两页(就像Word上的默认行为一样)

我希望这会有所帮助。

答案 10 :(得分:1)

我已经挖掘了这些问题好几天了,终于找到了完美的解决方案。您可以参考此项目phpwkhtmltopdf。查看目录article,您将找到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,你一定想知道这些 如果您希望gist for wkhtmltopdf

,请查看要点

答案 11 :(得分:1)

I was facing the same issue add after a lot of trial n errors this css solved the issue

tr { display: inline-table; }

答案 12 :(得分:1)

你有桌头吗?和桌子身体?

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

这是表格的正确格式,而大多数浏览器可能不在乎,转换器就像你提到的那样,如果你遗失{{1} }或<tbody>代码我建议你先尝试添加。

答案 13 :(得分:1)

我找到了这个荒谬的解决方案,但对我来说效果很好:)

我只是放了一个非常长的rowpan列,就像这样

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

然后表格不会中断。

答案 14 :(得分:1)

对于仍然遇到此问题的人,需要记住的一件事是必须是 body 的直接子项,否则css会赢得&#t; t工作(至少是我发生的事情)。

答案 15 :(得分:1)

上面的答案对我不起作用。我必须专门禁用缩放选项my 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

答案 16 :(得分:1)

除了Nanotelep所说的内容之外,这里还有手动表格分页算法的工作实现。 https://github.com/AAverin/JSUtils/tree/master/wkhtmltopdfTableSplitHack

答案 17 :(得分:0)

为避免分页符,我们可以使用避免分页符css选项。

tr { page-break-inside: avoid; }

中断所有内容(图片/文字),并将其显示在下一页

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

答案 18 :(得分:0)

使用相应的类添加此 CSS

#main_div {
        position: relative;
        width: 672px; /* find your width in px based on the page margins */
    }
tr td {
        page-break-before: auto;
        page-break-inside: avoid !important;
    }

但最重要的是为包含表格(或某些父 div)的容器提供以像素为单位的固定宽度。应该适用于大多数 (WebKit) pdf 生成器并允许它们正确计算高度。

我可以确认在 kubuntu 20.04 中使用 wkhtmltopdf 0.12.6(带有补丁的 qt)对我有用