TCPDF 在多个页面上拆分 html 表

Posted

技术标签:

【中文标题】TCPDF 在多个页面上拆分 html 表【英文标题】:TCPDF split html table on multiple pages 【发布时间】:2012-06-28 14:06:35 【问题描述】:

我使用 TCPDF 来输出一个 html 表,在我的示例中,这不是我唯一需要修改的,所以我需要一些规则来渲染我的页面。 到目前为止,TCPDF 在我看来是一个功能强大的库,所以我希望不要尝试另一个库。

我的问题是我需要将表格标题添加到表格将出现的每个新页面,但我还有其他信息要写入此 pdf,必须没有表格标题,所以我不能使用重写tcpdf 中的 header 方法。

<table border="0" cellspacing="0" cellpadding="0" align="center"  ><tr><td><table border="0" cellspacing="0" cellpadding="3" align="left"  ><tr><td class="TableHeader"   style="padding: 5px; border-top: 1px solid #000000; border-left: 1px solid #000000; border-bottom: 1px solid #E4E9EC;" >Nr.</td><td class="TableHeader"  style=" padding: 5px; border-top: 1px solid #000000; border-bottom: 1px solid #E4E9EC;" >Denumire</td><td class="TableHeader"  align="left" style=" padding: 5px; border-top: 1px solid #000000; border-bottom: 1px solid #E4E9EC;" >Cod</td><td class="TableHeader"  align="center" style=" padding: 5px; border-top: 1px solid #000000; border-bottom: 1px solid #E4E9EC;" >Cant.</td><td class="TableHeaderLast" align="right"  style=" padding: 5px; border-top: 1px solid #000000; border-bottom: 1px solid #E4E9EC;" >Pret unitar<br />fara TVA (RON)</td><td class="TableHeaderLast" align="right"  style=" padding: 5px; border-bottom: 1px solid #E4E9EC; border-top: 1px solid #000000; border-right: 1px solid #000000;" >Pret total<br />fara TVA (RON)</td></tr></table></td></tr></table><table border="0" cellspacing="0" cellpadding="0" align="center"  id="Container"><tr><td><table border="0" cellspacing="0" cellpadding="3" align="left"  ><tr><td class="TableHeader"   style="padding: 5px; border-left: 1px solid #000000;" >&nbsp;</td><td class="TableHeader"  style=" padding: 5px;" >&nbsp;</td><td class="TableHeader"  style=" padding: 5px;" >&nbsp;</td><td class="TableHeader"  style=" padding: 5px;" >&nbsp;</td><td class="TableHeaderLast" align="right"  style=" padding: 5px;" >&nbsp;</td><td class="TableHeaderLast" align="right"  style=" padding: 5px; border-right: 1px solid #000000;" >&nbsp;</td></tr><tr style="border-bottom: 1px solid #ccc"><td class="TableRow" style="padding: 5px; border-bottom: 1px solid #E4E9EC; border-left: 1px solid #000000; ">1</td><td class="TableRow" style="padding: 5px; border-bottom: 1px solid #E4E9EC;"><b>sectiune1</b></td><td class="TableRow" colspan="5" style="padding: 5px; border-bottom: 1px solid #E4E9EC; border-right: 1px solid #000000;">&nbsp;</td></tr><tr style="border-bottom: 1px solid #ccc"><td class="TableRow" style="padding: 5px; border-left: 1px solid #000000;border-bottom: 1px solid #E4E9EC; ">1.1</td><td class="TableRow" style="padding: 5px;border-bottom: 1px solid #E4E9EC; ">UNI-Cazan mixt AIREX 25 2S BICOMB MODUL  </td><td class="TableRow" align="left" style="padding: 5px;border-bottom: 1px solid #E4E9EC; ">94456&nbsp;</td><td class="TableRow"  align="center" style="padding: 5px;border-bottom: 1px solid #E4E9EC;">99999</td><td class="TableRow" align="right" style="padding: 5px;border-bottom: 1px solid #E4E9EC; ">24.623,00</td><td class="TableRow" align="right"  style="padding: 5px;  border-right: 1px solid #000000;border-bottom: 1px solid #E4E9EC;">2.462.275.377,00</td></tr><tr style="border-bottom: 1px solid #ccc"><td class="TableRow" style="padding: 5px; border-left: 1px solid #000000;border-bottom: 1px solid #E4E9EC; ">1.2</td><td class="TableRow" style="padding: 5px;border-bottom: 1px solid #E4E9EC; ">UNI-Cazan mixt AIREX 25 2S BICOMB MODUL  </td><td class="TableRow" align="left" style="padding: 5px;border-bottom: 1px solid #E4E9EC; ">94456&nbsp;</td><td class="TableRow"  align="center" style="padding: 5px;border-bottom: 1px solid #E4E9EC;">99999</td><td class="TableRow" align="right" style="padding: 5px;border-bottom: 1px solid #E4E9EC; ">24.623,00</td><td class="TableRow" align="right"  style="padding: 5px;  border-right: 1px solid #000000;border-bottom: 1px solid #E4E9EC;">2.462.275.377,00</td></tr><tr style="border-bottom: 1px solid #ccc"><td class="TableRow" style="padding: 5px; border-bottom: 1px solid #000; border-left: 1px solid #000000; ">&nbsp;</td><td class="TableRow"  style="padding: 5px; border-bottom: 1px solid #000; "><b> TOTAL sectiune1:</b></td><td class="TableRow" style="padding: 5px; border-bottom: 1px solid #000; "> &nbsp;</td><td class="TableRow" style="padding: 5px; border-bottom: 1px solid #000; "> &nbsp;</td><td class="TableRowLast" colspan="2" align="right" style="padding: 5px; border-bottom: 1px solid #000; border-right: 1px solid #000000; "><b>4.924.550.754,00</b></td></tr><tr style="border-bottom: 1px solid #ccc"><td class="TableRow" style="padding: 5px; border-top: 1px solid #000; border-bottom: 1px solid #000; ">&nbsp;</td><td class="TableRow" style="padding: 5px; border-top: 1px solid #000; border-bottom: 1px solid #000;">&nbsp;</td><td class="TableRow" colspan="5" style="padding: 5px; border-top: 1px solid #000; border-bottom: 1px solid #000; ">&nbsp;</td></tr><tr style="border-bottom: 1px solid #ccc"><td class="TableRow" style="padding: 5px; border-top: 1px solid #000; border-bottom: 1px solid #E4E9EC; border-left: 1px solid #000000; ">2</td><td class="TableRow" style="padding: 5px; border-bottom: 1px solid #E4E9EC; border-top: 1px solid #000;"><b>sectiune2</b></td><td class="TableRow" colspan="5" style="padding: 5px; border-bottom: 1px solid #E4E9EC; border-right: 1px solid #000000; border-top: 1px solid #000;">&nbsp;</td></tr><tr style="border-bottom: 1px solid #ccc"><td class="TableRow" style="padding: 5px; border-left: 1px solid #000000;border-bottom: 1px solid #E4E9EC; ">2.1</td><td class="TableRow" style="padding: 5px;border-bottom: 1px solid #E4E9EC; ">ICI-Cazan condensatie MONOLITE 75-JB</td><td class="TableRow" align="left" style="padding: 5px;border-bottom: 1px solid #E4E9EC; ">81020076&nbsp;</td><td class="TableRow"  align="center" style="padding: 5px;border-bottom: 1px solid #E4E9EC;">99999</td><td class="TableRow" align="right" style="padding: 5px;border-bottom: 1px solid #E4E9EC; ">34.719,00</td><td class="TableRow" align="right"  style="padding: 5px;  border-right: 1px solid #000000;border-bottom: 1px solid #E4E9EC;">3.471.865.281,00</td></tr><tr style="border-bottom: 1px solid #ccc"><td class="TableRow" style="padding: 5px; border-bottom: 1px solid #000; border-left: 1px solid #000000; ">&nbsp;</td><td class="TableRow"  style="padding: 5px; border-bottom: 1px solid #000; "><b> TOTAL sectiune2:</b></td><td class="TableRow" style="padding: 5px; border-bottom: 1px solid #000; "> &nbsp;</td><td class="TableRow" style="padding: 5px; border-bottom: 1px solid #000; "> &nbsp;</td><td class="TableRowLast" colspan="2" align="right" style="padding: 5px; border-bottom: 1px solid #000; border-right: 1px solid #000000; "><b>3.471.865.281,00</b></td></tr><tr style="border-bottom: 1px solid #ccc"><td class="TableRow" style="padding: 5px; border-top: 1px solid #000; border-bottom: 1px solid #000; ">&nbsp;</td><td class="TableRow" style="padding: 5px; border-top: 1px solid #000; border-bottom: 1px solid #000;">&nbsp;</td><td class="TableRow" colspan="5" style="padding: 5px; border-top: 1px solid #000; border-bottom: 1px solid #000; ">&nbsp;</td></tr><tr><td class="TableTotal"  style=" padding: 5px; border-left: 1px solid #000000;"></td><td colspan="3" class="TableTotal"  style=" padding: 5px; " ><b>Total sectiune1:</b></td><td align="right" class="TableTotal" style=" padding: 5px; " ><b>&nbsp;</b></td><td class="TableTotal" align="right" style=" padding: 5px; border-right: 1px solid #000000;" ><b>4.924.550.754,00 </b></td></tr><tr><td class="TableTotal"  style=" padding: 5px; border-left: 1px solid #000000;"></td><td colspan="3" class="TableTotal"  style=" padding: 5px; " ><b>Total sectiune2:</b></td><td align="right" class="TableTotal" style=" padding: 5px; " ><b>&nbsp;</b></td><td class="TableTotal" align="right" style=" padding: 5px; border-right: 1px solid #000000;" ><b>3.471.865.281,00 </b></td></tr><tr><td class="TableTotal"  style=" padding: 5px; border-left: 1px solid #000000;border-top: 1px solid #E4E9EC; "></td><td colspan="4" class="TableTotal"  style=" padding: 5px;border-top: 1px solid #E4E9EC; " ><b>Total oferta (RON):</b></td><td colspan="2" align="right" class="TableTotal" style=" padding: 5px; border-right: 1px solid #000000;border-top: 1px solid #E4E9EC; " ><b>8.396.416.035,00 </b></td></tr><tr><td class="TableTotal"  style=" padding: 5px; border-left: 1px solid #000000;border-bottom: 1px solid #000000;"></td><td colspan="4" class="TableTotal"  style=" padding: 5px;border-bottom: 1px solid #000000;" ><b>Total oferta (RON cu TVA inclus):</b></td><td colspan="2" align="right" class="TableTotal" style=" padding: 5px; border-right: 1px solid #000000;border-bottom: 1px solid #000000;" ><b>10.411.555.883,40 </b></td></tr></table></td></tr></table>

我想到了以下解决方案:如果我能以某种方式将此 html 拆分为行并逐行写入 pdf,以便在我写到页脚时可以回滚,然后我添加一个新页面,但是有一个专业问题,我收到各种警告,因为 html 表格标签没有关闭。 这是我的代码:

$pdf->setAutoPageBreak(false);
$pdf->startTransaction();
$html = new simple_html_dom();
$html->load($data);
$single = $html->find('#Container', 0);
if($single)

 $rows = $single->getElementsByTagName('tr');
 $rows = $rows[0]->getElementsByTagName('tr');

 if($rows)
   for($i=1;$i<(count($rows)-1);$i++)
     $pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', '<table>', $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=false);
     $pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', $rows[$i]->outertext, $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=false);
     $pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', '</table>', $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=false);

   if ($pdf->getY() > $pdf->getPageHeight() - 30) 
       $pdf->rollbackTransaction(true);
       $pdf->AddPage();
       $pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', '<table>', $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=false);
       $pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', $rows[$i]->outertext, $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=false);
       $pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', '</table>', $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=false);
        
    
   


    $pdf->commitTransaction();
    $pdf->setAutoPageBreak(true, 30);

我快速浏览了这 2 篇文章,也许有人会觉得这很方便: Some paging with multicell 和Another paging with multicell。我发现这 2 个值得作为解决方案逻辑的示例,但与 tcpdf 一起使用的方法在我看来有点奇怪。

【问题讨论】:

嗨@decebal 我可以得到你的代码来解决这个问题吗? @Abdullah 不确定你的意思?如果您要求使用上面的许可,您不需要它,请随意使用它。 不,我想要解决方案文件。 【参考方案1】:

转到 TCPDF 并选择 Example 48,您将看到一个带有 &lt;thead&gt; 元素的示例。

【讨论】:

应该读到“thead”元素。我还发现 HTML 应该经过验证才能正常工作。【参考方案2】:

我认为您的解决方案很好。我能想到的唯一其他方法是使用固定宽度的多单元格,这可能会很痛苦,但会为您提供静态列宽。

我注意到了一些问题:

    您的事务包含整个文档,回滚应该将文档重置为空。 您的警告很可能是由于您传递的部分 html 代码无法呈现到 writeHTMLCell。 (您只传递 或
    单独时无法呈现) 如果您将每一行包装在表格标签中,您的列将不会对齐。最好的办法是将该页面上的行包装在一个表格块中。

试试这些改变,告诉我结果如何

$pdf->setAutoPageBreak(false);
//$pdf->startTransaction(); // Moved
$html = new simple_html_dom();
$html->load($data);
$single = $html->find('#Container', 0);
if($single)

    $rows = $single->getElementsByTagName('tr');
    $rows = $rows[0]->getElementsByTagName('tr');

    if($rows) 
        $pdf->startTransaction(); // Start transaction only because we may need it
        // Header for html, this starts the html and can optionally insert the header row as the first row on every new page.
        $html_header = '<tr><td>Name</td><td>Age</td></tr>'; 
        $html_buffer = '<table>'.$html_header;
        for($i=1;$i<(count($rows)-1);$i++)
            $pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', $html_buffer.$rows[$i]->outertext.'</table>', $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=false);

            if ($pdf->getY() < ($pdf->getPageHeight() - 30))  // Note the less-than operator
                // We might be able to add some more text, so undo that
                $pdf->rollbackTransaction(true);
                // And store the html
                $html_buffer .= $rows[$i]->outertext;
            else
                // We exceeded our limit
                $pdf->rollbackTransaction(true);
                // Write last known good table
                $pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', $html_buffer.'</table>', $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=false);
                // Add a new page
                $pdf->AddPage();
                // End this transaction
                $pdf->commitTransaction();
                // Start a new transaction
                $pdf->startTransaction();
                // Reset html buffer
                $html_buffer = '<table>'.$html_header;
                // Add line we couldn't fit on last page to html buffer
                $html_buffer .= $rows[$i]->outertext;
            
        
        // There is still information in our buffer and it fits on a single page
        $pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', $html_buffer.'</table>', $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=false);
        // Final commit
        $pdf->commitTransaction(); 
    

$pdf->setAutoPageBreak(true, 30);

这会将页面上的所有内容包装在一个表格块中,以便列将在该页面上对齐。 (它们可能仍然因页面而异)另外,我让您能够根据需要将自己的标题添加到每个新页面。只需将 $html_header 更改为您自己的标题行代码即可。

你说的对,TCPDF 可能会让人困惑,但它也非常强大,一旦你掌握了它的窍门,你就可以制作一些非常好的文档。

【讨论】:

我做了以下修改:用 $table_tag 替换了 '',因为我需要一些样式,否则它就像一个魅力 10 倍的男人:) 我遇到了一些其他问题,所以我需要添加这个 if(!strpos($rows[$i-1]->outertext,$rows[$i]->outertext)) $ html_buffer .= $rows[$i]->outertext;

以上是关于TCPDF 在多个页面上拆分 html 表的主要内容,如果未能解决你的问题,请参考以下文章

C#将一个excel工作表根据指定范围拆分为多个excel文件

在一个页面上将一个视图模型拆分为多个表单

如何根据屏幕大小将Epub Html拆分为多个页面

TCPDF 中的手动分页符

最好有数百列或拆分成多个表?

如何拆分excel 多个工作表