コンテンツにスキップ

大きな HTML テーブルを複数ページに分割する

1 つの大きな <table>writeHtml() に渡します。エンジンは、そのテーブルを行に必要な数の PDF ページへ分割します。<thead> は各ページの先頭で繰り返されるため、各ページが完結したテーブルとして機能します。このレシピでは、複数ページに流し込まれる 91 行のレポートをレンダリングします。テーブルを自分で分割したり、改ページを計算したりする必要はありません。

Terminal window
composer require nextpdf/core

テーブルが 1 ページよりも高い場合は、1 つの <table> 要素のままにします。エンジンは各行を計測し、使用可能なページの高さまで行を配置してから新しいページを開き、同じテーブルを継続します。<thead> の行は、各継続ページの先頭で再度レンダリングされます。継続ページではドキュメントの上下マージンが維持されるため、新しいページの最初の行はページの端ではなく、上マージンの下から始まります。

ヘッダーセルは <thead> に、データ行は <tbody> に配置します。繰り返されるのは <thead> のみです。各行は分割できる状態にしてください。使用可能なページの高さよりも高い単一の行はページ分割できず、UnsplittableContentException を発生させます。

シンボル場所役割
Document::writeHtml(string $html): staticNextPDF\Core\Concerns\HasTextOutputHTML のレンダリングと、必要に応じたテーブルのページ分割
Document::createStandalone(): selfNextPDF\Core\Documentスタンドアロンドキュメントの作成
Document::addPage(): staticNextPDF\Core\Document最初のページを開き、ページサイズとマージンを設定
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$rows = '';
for ($i = 1; $i <= 91; $i++) {
$rows .= "<tr><td>{$i}</td><td>Item {$i}</td><td>In stock</td></tr>";
}
$doc = Document::createStandalone();
$doc->addPage();
$doc->writeHtml(
'<table>'
. '<thead><tr><th>#</th><th>Name</th><th>Status</th></tr></thead>'
. "<tbody>{$rows}</tbody>"
. '</table>'
);
$doc->save(__DIR__ . '/large-table.pdf');

91 行は複数ページに流し込まれ、#/Name/Status のヘッダーが各ページで繰り返されます。

この自己完結したサンプルでは、ヘッダーにスタイルを付け、行をしま模様にして、ハーネスで指定されたパスに PDF を書き込みます。

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$rows = '';
for ($i = 1; $i <= 91; $i++) {
$bg = $i % 2 === 0 ? '#F8FAFC' : '#FFFFFF';
$rows .= "<tr style=\"background-color: {$bg};\">"
. "<td style=\"border: 1px solid #CBD5E1; padding: 4px;\">{$i}</td>"
. "<td style=\"border: 1px solid #CBD5E1; padding: 4px;\">Item {$i}</td>"
. "<td style=\"border: 1px solid #CBD5E1; padding: 4px;\">In stock</td>"
. '</tr>';
}
$html = <<<HTML
<table style="width: 100%; border-collapse: collapse;">
<thead>
<tr style="background-color: #1E3A8A; color: #FFFFFF;">
<th style="border: 1px solid #1E3A8A; padding: 6px;">#</th>
<th style="border: 1px solid #1E3A8A; padding: 6px;">Name</th>
<th style="border: 1px solid #1E3A8A; padding: 6px;">Status</th>
</tr>
</thead>
<tbody>{$rows}</tbody>
</table>
HTML;
$doc = Document::createStandalone();
$doc->setTitle('Inventory report');
$doc->addPage();
$doc->writeHtml($html);
$out = getenv('NEXTPDF_OUT');
$doc->save($out !== false ? $out : __DIR__ . '/paginate-large-html-tables.pdf');
echo "Wrote the paginated table PDF\n";

継続ページでは、ドキュメントの上下マージンが使用されます。改ページ後の最初の行は上マージンの下から始まり、改ページ前の最後の行は下マージンの上で止まります。これにより、長いテーブルがページの端で切り取られるのを防ぎます。同じ規則が、複数ページにわたるブロックと複数ページにわたるテーブルの両方に適用されます。

  • ページ分割の警告は、成功時には出力されません。 テーブルが複数ページにわたってきれいに流れる場合、警告は出力されません。エンジンが TABLE_ROW_OVERFLOW 警告を発生させるのは、レイアウトが劣化した場合だけです。具体的には、改ページのシンクがない場合、または行をページの先頭に持ってくるために再配置しなければならない場合です。この警告は、失敗ではなく、テーブルを簡素化するシグナルとして扱ってください。
  • ヘッダーは <thead> に入れてください。 繰り返されるのは <thead> の行のみです。<tbody> に残されたヘッダー行は 1 回だけ表示されます。
  • 行は分割可能でなければなりません。 使用可能なページの高さよりも高い単一の行は UnsplittableContentException を発生させます。その行のコンテンツを分割するか、短くしてください。
  • rowspan は改ページをまたぐと機能が低下します。 ページ境界をまたぐ rowspan のセルはフラグメント化されます(ADR-007)。改ページをまたいでも一体のまま保つ必要があるグループ化には、代わりにカテゴリーヘッダー行を使用してください。サポートされていない CSS 機能を参照してください。

レンダリングは行数に対して線形にスケールします。エンジンは出力をページごとにストリーミングし、ドキュメントツリーを保持し続けることはないため、長いテーブルのメモリ使用量がページ数とともに増えることはありません。このレシピのバジェットは wall_ms: 2000, peak_mb: 96 です。

ユーザー指定のデータでは行数とセルの長さを検証し、出力サイズを抑えてください。エンジンはテキストを解釈するのではなくレンダリングし、スクリプトを実行することもありません。

記述仕様条項reference_id
テーブルのヘッダーグループは、テーブルが分割されるフラグメンテーションコンテナーにわたって繰り返されます。W3C CSS Tables 3css_tables_3#x1.x7.x253622ccb1bce2a0cc53bd70919fa4633a9376e2050f63a31a3fde9cb6595ec78

該当なし。