Przejdź do głównej zawartości

Dzielenie dużej tabeli HTML na strony

Przekaż jedną dużą <table> do writeHtml(). Silnik dzieli ją na tyle stron PDF, ile wymagają wiersze. <thead> powtarza się u góry każdej strony, więc każda strona zachowuje kontekst kompletnej tabeli. Ten przepis renderuje 91-wierszowy raport, który rozciąga się na kilka stron. Nie trzeba samodzielnie dzielić tabeli ani obliczać podziałów stron.

Okno terminala
composer require nextpdf/core

Gdy tabela jest wyższa niż jedna strona, zachowaj ją jako pojedynczy element <table>. Silnik mierzy każdy wiersz, wypełnia użyteczną wysokość strony, otwiera nową stronę i kontynuuje tę samą tabelę. Wiersze <thead> ponownie renderuje u góry każdej strony kontynuacji. Strony kontynuacji zachowują górny i dolny margines dokumentu, więc pierwszy wiersz na nowej stronie zaczyna się poniżej górnego marginesu, a nie przy krawędzi strony.

Umieść komórki nagłówka w <thead>, a wiersze danych w <tbody>. Powtarza się tylko <thead>. Każdy wiersz powinien dać się podzielić. Pojedynczy wiersz wyższy niż użyteczna wysokość strony nie może zostać podzielony między strony i zgłasza UnsplittableContentException.

SymbolLokalizacjaRola
Document::writeHtml(string $html): staticNextPDF\Core\Concerns\HasTextOutputRenderuje HTML i dzieli tabele na strony w miarę potrzeby.
Document::createStandalone(): selfNextPDF\Core\DocumentTworzy samodzielny dokument.
Document::addPage(): staticNextPDF\Core\DocumentOtwiera pierwszą stronę oraz ustawia rozmiar i marginesy strony.
<?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 wierszy rozciąga się na kilka stron, a nagłówek #/Name/Status powtarza się na każdej z nich.

Ten samodzielny przykład stylizuje nagłówek, stosuje naprzemienne tło wierszy i zapisuje plik PDF pod ścieżką dostarczoną przez środowisko testowe.

<?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";

Strony kontynuacji używają górnego i dolnego marginesu dokumentu. Pierwszy wiersz po podziale strony zaczyna się poniżej górnego marginesu, a ostatni wiersz przed podziałem zatrzymuje się powyżej dolnego marginesu. Dzięki temu długa tabela nie zostaje przycięta przy krawędzi strony. Ta sama reguła dotyczy bloków wielostronicowych i tabel wielostronicowych.

  • Ostrzeżenia o dzieleniu na strony nie pojawiają się po udanym podziale. Gdy tabela płynnie przechodzi między stronami, silnik nie emituje żadnego ostrzeżenia. Silnik zgłasza ostrzeżenie TABLE_ROW_OVERFLOW tylko dla zdegradowanego układu: gdy nie ma odbiornika podziału strony albo gdy wiersz trzeba przenieść, aby rozpoczął stronę. Traktuj to ostrzeżenie jako sygnał do uproszczenia tabeli, a nie jako awarię.
  • Umieść nagłówek w <thead>. Powtarzają się tylko wiersze <thead>. Wiersz nagłówka pozostawiony w <tbody> pojawia się raz.
  • Wiersze muszą być podzielne. Pojedynczy wiersz wyższy niż użyteczna wysokość strony zgłasza UnsplittableContentException. Podziel treść tego wiersza albo go skróć.
  • rowspan jest degradowany przy podziale. Komórka rowspan, która przekracza granicę strony, jest fragmentowana (ADR-007). W przypadku grupowań, które muszą pozostać nienaruszone podczas dzielenia na strony, użyj zamiast tego wiersza nagłówka kategorii. Zobacz Nieobsługiwane funkcje CSS.

Renderowanie skaluje się liniowo z liczbą wierszy. Silnik strumieniuje wynik strona po stronie i nie przechowuje całego drzewa dokumentu, więc zużycie pamięci dla długiej tabeli nie rośnie wraz z liczbą stron. Budżet tego przepisu to wall_ms: 2000, peak_mb: 96.

Waliduj liczbę wierszy i długość komórek dla danych dostarczonych przez użytkownika, aby rozmiar wyjścia pozostał w ustalonych granicach. Silnik renderuje tekst, zamiast go interpretować, i nie uruchamia żadnego skryptu.

StwierdzenieSpecyfikacjaKlauzulareference_id
Grupa nagłówka tabeli powtarza się w kontenerach fragmentacji, na które dzielona jest tabela.W3C CSS Tables 3css_tables_3#x1.x7.x253622ccb1bce2a0cc53bd70919fa4633a9376e2050f63a31a3fde9cb6595ec78

Nie dotyczy.