Generuję raport pdf ze strony html z jedną tabelą .
W tym celu używam wkhtmltopdf .
kiedy generowany jest plik PDF, zrywa się gdziekolwiek w znaczniku tr .
Chcę tego uniknąć.
Generuję raport pdf ze strony html z jedną tabelą .
W tym celu używam wkhtmltopdf .
kiedy generowany jest plik PDF, zrywa się gdziekolwiek w znaczniku tr .
Chcę tego uniknąć.
Odpowiedzi:
Aktualizacja 17.09.2015: Sprawdź używaną wersję: mówi się, że wkhtmltopdf 0.12.2.4 rozwiązuje problem (nie sprawdzałem) .
Jest to znany problem w programie wkhtmltopdf. Algorytm łamania stron używany przez webkit (WK w WKhtmltopdf) nie działa dobrze w przypadku dużych tabel. Proponuję rozbić tabelę na mniejsze fragmenty, które można łatwiej podzielić na strony i często używać CSS:
table, tr, td, th, tbody, thead, tfoot {
page-break-inside: avoid !important;
}
Przyjrzyj się również następującym zagadnieniom wkhtmltopdf, w których znajdują się interesujące komentarze, które omawiają na przykład problem dzielenia tabel. Istnieje rozwiązanie JS, które programowo dzieli tabele w 168, które mogą ci pomóc (chociaż go nie używam).
Aktualizacja 08.11.2013
Jest wiele dyskusji na ten temat w numerze 168, do którego link znajduje się powyżej. Ktoś zdołał skompilować wersję wkhtmltopdf, która obsługuje lepsze łamanie tabel, ale niestety wygląda na to, że nie została oficjalnie wydana i może zawierać inne błędy. Nie wiem, jak to zdobyć i nie wiem, jak skompilować w systemie Windows, ale każdy zainteresowany może sprawdzić na przykład komentarz tutaj (zobacz nową aktualizację poniżej).
Aktualizacja 24.02.2014 Z przyjemnością usłyszysz, że w wkhtmltopdf 0.12 między innymi ta funkcja została znacznie ulepszona. Jednak poczekaj na wersję 0.12.1 i dokładnie przetestuj, zanim zaczniesz używać jakiejkolwiek nowej wersji, nadal jest trochę niestabilna, chociaż nowi faceci pracujący z antialize wykonują świetną robotę (ashkulz rock)! Bądź na bieżąco na wkhtmltopdf.org i github . Witryna Google Code jest przestarzała i powoli podlega migracji.
display: inline-block
. Zmieniłem to na block
i ze zmianami nad tym wszystkim zaczęło działać!
To stary post, ale ponieważ traciłem dużo czasu na szukanie odpowiedniego rozwiązania, wstawię go tutaj, może się komuś przyda.
A więc z tego, co przeczytałem, problem z
page-break-inside: avoid
jest to, że to nie działa. Ale tak naprawdę, jeśli ustawisz to na elemencie, który ma display:block
to działa zgodnie z oczekiwaniami (jak zauważono gdzieś w SO). więc dla prostej struktury tabeli css z
td div, th div{
page-break-inside: avoid;
}
i strukturę tabeli
<table>
....
<tr>
<td><div>some text</div></td>
<td><div>more text</div></td>
</tr>
....
</table>
będzie działać zgodnie z oczekiwaniami.
Miałem trochę bardziej skomplikowany przypadek z rozpiętościami rzędów, więc rozwiązanie z góry rozbijało go do pokoju, co nie było pożądanym efektem. Rozwiązałem to za pomocą elementów div dla każdego zbioru linii rozpiętego na wiersz. Mój jquery js wykonuje całą robotę:
$(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;
}
Nie wiem, czy wszystko jest potrzebne i nie sądzę, że jest to idealne rozwiązanie, ale spełnia swoje zadanie. Testowany tylko na chromie
Od wersji 0.12 ten problem został rozwiązany, ale czasami, gdy tabela jest zbyt długa, aby zmieścić się na stronie, wkhtmltopdf dzieli ją na dwie części i powtarza nagłówki kolumn na nowej stronie, a te nagłówki kolumn są nakładane na pierwszy wiersz.
Znalazłem tymczasowe rozwiązanie tego problemu w sekcji problemów wkhtmltopdf github: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2531
Po prostu dodaj te linie do swojego widoku css:
tr {
page-break-inside: avoid;
}
Zagłębiałem się w ten problem przez wiele dni i wreszcie znalazłem idealne rozwiązanie. Możesz odwołać się do tego projektu phpwkhtmltopdf . Zajrzyj do katalogu, article
a znajdziesz 3 rozwiązania dla 3 problemów. Krótko mówiąc, ostatecznym rozwiązaniem jest dodanie stylu 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;
}
Jeśli jesteś Chińczykiem, możesz śmiało sprawdzić tę stronę关于 wkhtmltopdf , 你 一定 想 知道 这些 Przeczytaj streszczenie , jeśli chcesz skorzystać z wkhtmltopdf
Okazało się, że wkhtmltopdf 0.12.2.1 i nowsze wersje rozwiązały ten problem.
W moim przypadku z jakiegoś powodu żadna z poprzednich odpowiedzi nie zadziałała. To, co ostatecznie zadziałało, było w rzeczywistości połączeniem kilku rzeczy.
Zainstalowałem (w Ubuntu 16.04) opakowanie Pythona Wkhtmltopdf o nazwie pdfkit przy użyciu pip3, a następnie zamiast instalować Wkhtmltopdf przez apt-get zainstalowałem statyczny plik binarny (wersja 0.12.3), wykonując poniższy skrypt, pobrany stąd
#!/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/
Dodano ten CSS (zgodnie z sugestią w jednej z odpowiedzi tutaj):
tr, td div, th div{
page-break-inside: avoid;
}
A następnie dodaj także<thead>
i <tbody>
tagi, jak sugerowano tutaj (bez tego tabela nadal by się zepsuła):
<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>
Dzięki tym modyfikacjom mogę teraz z powodzeniem używać szablonów Mako do generowania kodu HTML, a następnie przesyłać go do Wkhtmltopdf i uzyskać pięknie podzielony na strony plik PDF.
Próbowałem wszelkiego rodzaju manipulacji na moich stołach, ale nic, co próbowałem, nie mogło powstrzymać podziałów strony na środek rzędu. W desperacji wypróbowałem różne wersje i znalazłem następujące:
Wkhtmltopdf 0.12.2.1: Zły
Wkhtmltopdf 0.12.3: Zły
Wkhtmltopdf 0.12.1: Dobrze
Moim rozwiązaniem było przejście na wersję 0.12.1, co rozwiązało moje problemy. To prawda, mogło to być częściowo spowodowane tym, że nie byłem super OCD w moim html, ale ponieważ HTML jest generowany w TinyMCE (przez użytkowników), tak naprawdę nie mam wielkiego wyboru.
Ponadto zagnieżdżone tabele nie działają w żadnej wersji dla mnie.
Jak używać podziałów stron w pliku PDF bez przerywania tr?
Oto rozwiązanie, którego możesz użyć w dowolnym pliku html .....
Po uruchomieniu tr musisz wziąć div wewnątrz tr i przekazać ten css do div:
<tr>
<div style="page-break-inside:avoid !important; page-break-after:auto !important; overflow: hidden; display:block !important; width:100% ">
</tr>
Miałem do czynienia z tym samym problemem, dodając po wielu próbnych n błędach, ten CSS rozwiązał problem
tr {
display: inline-table;
}
Oprócz tego, co mówi Nanotelep, oto działająca implementacja algorytmu ręcznego łamania stron tabeli. https://github.com/AAverin/JSUtils/tree/master/wkhtmltopdfTableSplitHack
Powyższe odpowiedzi mi nie pomogły. Musiałem specjalnie wyłączyć opcję powiększenia w mojej konfiguracji pdfkit.
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
Dla każdego, kto nadal ma z tym problemy, jedną rzeczą do zapamiętania jest to, że tabela musi być bezpośrednim dzieckiem ciała , w przeciwnym razie css nie zadziała (przynajmniej tak się stało ze mną).
display: table-cell;
zastosowaniem. Stworzenie tych stylów @media only screen
naprawiło podziały stron. Jeśli nie możesz uruchomić podziałów stron, spróbuj podzielić i podbić, usuwając połowę CSS etapami i sprawdzając, czy to działa.
Inna opcja: umieść każdy tr
osobno, tbody
a następnie zastosuj reguły css peage break do pliku tbody
. Tabele obsługują wiele plikówtbody
s.
Trochę dodatkowych znaczników, ale dla mnie działa przyzwoicie.
Rozwiązałem problem, stosując kombinację kilku sugerowanych rozwiązań.
Owinąłem tabelę w div i zdefiniowałem następujący 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;
}
Struktura tabeli po zakończeniu została zdefiniowana jako następujący przykład:
<div class="wrapping-div">
<table>
<tbody>
<tr>
<th>
header
</th>
<td>
content
</td>
</tr>
</tbody>
</table>
</div>
Nie musiałem tworzyć żadnego elementu div wewnątrz znaczników td lub th.
Ważne rzeczy, które zauważyłem podczas próby rozwiązania problemu:
Mam nadzieję, że to pomoże.
Dużo zmagałem się z tym problemem, używając najnowszej wersji h4cc / wkhtmltopdf-amd64 0.12.4 i wreszcie udało mi się go uruchomić, obniżając wersję pakietu do 0.12.3
!
Aby uniknąć podziału strony, możemy użyć opcji css unikania podziału strony.
tr { page-break-inside: avoid; }
Przerwij dowolną treść (obraz / tekst) i umieść ją na następnej stronie
.sample-image { page-break-before: always; }
Czy masz głowę stołu? i korpus stołu?
<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>
To jest właściwe formatowanie tabeli, podczas gdy większości przeglądarek nie obchodziło to mniej, konwertery takie jak ten, o którym wspomniałeś, mogą, jeśli brakujące <tbody>
lub <th>
tagi sugeruję, abyś spróbował najpierw je dodać.