Tôi đang tạo báo cáo pdf từ trang html với một bảng .
Tôi đang sử dụng wkhtmltopdf cho mục đích này.
khi pdf được tạo, nó bị hỏng ở bất kỳ đâu trong thẻ tr .
Tôi muốn tránh nó.
Tôi đang tạo báo cáo pdf từ trang html với một bảng .
Tôi đang sử dụng wkhtmltopdf cho mục đích này.
khi pdf được tạo, nó bị hỏng ở bất kỳ đâu trong thẻ tr .
Tôi muốn tránh nó.
Câu trả lời:
Cập nhật 17.09.2015: Kiểm tra phiên bản bạn đang sử dụng: wkhtmltopdf 0.12.2.4 được cho là khắc phục sự cố (Tôi chưa kiểm tra) .
Đây là một vấn đề đã biết trong wkhtmltopdf. Thuật toán ngắt trang được sử dụng bởi webkit (WK trong WKhtmltopdf) không thực sự hoạt động tốt cho các bảng lớn. Tôi khuyên bạn nên chia bảng thành các phần nhỏ hơn để dễ dàng chia thành các trang hơn và sử dụng css nhiều:
table, tr, td, th, tbody, thead, tfoot {
page-break-inside: avoid !important;
}
Ngoài ra, hãy xem các vấn đề wkhtmltopdf sau đây, họ có những nhận xét thú vị thảo luận về vấn đề tách bảng chẳng hạn. Có một giải pháp JS tách các bảng theo chương trình trong 168 có thể giúp bạn (tôi không sử dụng nó).
Cập nhật 08.11.2013
Có nhiều cuộc thảo luận về vấn đề này trong vấn đề 168 được liên kết ở trên. Ai đó đã quản lý để biên dịch phiên bản wkhtmltopdf hỗ trợ ngắt bảng tốt hơn, nhưng rất tiếc, có vẻ như nó không được phát hành chính thức và có thể chứa các lỗi khác. Mình không biết cách lấy và cũng không biết biên dịch trên Windows, nhưng ai quan tâm có thể kiểm tra ví dụ bình luận tại đây (xem bản cập nhật mới bên dưới).
Cập nhật 24.02.2014 Bạn sẽ rất vui khi biết rằng trong wkhtmltopdf 0.12, tính năng này trong số những tính năng khác đã được cải thiện rất nhiều. Tuy nhiên, hãy đợi 0.12.1 và kiểm tra kỹ lưỡng trước khi bắt đầu sử dụng bất kỳ phiên bản mới nào, nó vẫn còn một chút không ổn định mặc dù những người mới làm việc với antialize đang làm rất tốt (đá ashkulz)! Cập nhật liên tục tại wkhtmltopdf.org và github . Trang web mã google đã lỗi thời và đang dần di chuyển.
display: inline-block
. Đã thay đổi nó thành block
và những thay đổi ở trên đều bắt đầu hoạt động!
Đó là bài viết cũ, nhưng vì tôi đã mất rất nhiều thời gian để tìm giải pháp thích hợp, tôi sẽ đưa nó ở đây, có thể nó sẽ hữu ích cho ai đó.
Vì vậy, từ những gì tôi đọc, vấn đề với
page-break-inside: avoid
là nó không hoạt động. Nhưng thực sự nếu bạn đặt nó trên phần tử có display:block
nó hoạt động như mong đợi (như đã lưu ý ở đâu đó trong SO). vì vậy đối với cấu trúc đơn giản của bảng css với
td div, th div{
page-break-inside: avoid;
}
và cấu trúc bảng
<table>
....
<tr>
<td><div>some text</div></td>
<td><div>more text</div></td>
</tr>
....
</table>
sẽ hoạt động như mong đợi.
Tôi gặp trường hợp phức tạp hơn một chút với ghế chèo thuyền, vì vậy giải pháp từ phía trên là phá vỡ nó thành đỉnh, điều này không mang lại hiệu quả mong muốn. Tôi đã giải quyết nó bằng cách sử dụng div cho mỗi bộ dòng được phân tách hàng. Js jquery của tôi đang làm tất cả công việc:
$(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;
}
Tôi không biết liệu mọi thứ có cần thiết hay không và tôi không nghĩ nó hoàn hảo, nhưng nó làm được việc. Chỉ thử nghiệm trên chrome
Kể từ 0,12, vấn đề này đã được giải quyết nhưng đôi khi, khi một bảng quá dài để vừa với trang, wkhtmltopdf sẽ chia nó thành hai phần và lặp lại các tiêu đề cột trên trang mới và các tiêu đề cột này xuất hiện chồng lên hàng đầu tiên.
Tôi đã tìm thấy giải pháp tạm thời cho vấn đề này trên phần wkhtmltopdf github sự cố: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2531
Chỉ cần thêm dòng này vào css xem của bạn:
tr {
page-break-inside: avoid;
}
Tôi đã nghiên cứu vấn đề này trong nhiều ngày và cuối cùng đã tìm ra giải pháp hoàn hảo. Bạn có thể tham khảo dự án phpwkhtmltopdf này . Nhìn vào danh bạ article
và bạn sẽ tìm thấy 3 giải pháp cho 3 vấn đề. Tóm lại, giải pháp cuối cùng là thêm kiểu 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;
}
Nếu bạn là người Trung Quốc, vui lòng xem trang web này关于 wkhtmltopdf , 你 一定 想 知道 这些 Hãy xem ý chính nếu bạn muốn ý chính cho wkhtmltopdf
Tôi thấy rằng wkhtmltopdf 0.12.2.1 trở đi đã khắc phục sự cố này.
Trong trường hợp cụ thể của tôi vì một số lý do không có câu trả lời nào trước đây phù hợp với tôi. Những gì kết thúc hoạt động thực sự là sự kết hợp của nhiều thứ.
Tôi đã cài đặt (trong Ubuntu 16.04) trình bao bọc python Wkhtmltopdf được gọi là pdfkit bằng cách sử dụng pip3 và sau đó thay vì cài đặt Wkhtmltopdf qua apt-get, tôi đã cài đặt tệp nhị phân tĩnh (phiên bản 0.12.3) bằng cách làm theo tập lệnh bên dưới, lấy từ đây
#!/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/
Đã thêm CSS này (như được đề xuất trong một trong các câu trả lời ở đây):
tr, td div, th div{
page-break-inside: avoid;
}
Và sau đó cũng thêm <thead>
và <tbody>
các thẻ như được đề xuất ở đây (nếu không có những thứ này, bảng sẽ vẫn bị hỏng một cách xấu xí):
<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>
Với những sửa đổi này, giờ đây, tôi có thể sử dụng thành công các mẫu Mako để tạo HTML và sau đó cấp dữ liệu đó vào Wkhtmltopdf và có được một tệp PDF được phân trang đẹp mắt.
Tôi đã thử tất cả các cách thao tác với bảng của mình, nhưng không có gì tôi cố gắng có thể ngăn việc ngắt trang được đưa vào giữa một hàng. Trong tuyệt vọng, tôi đã thử các phiên bản khác nhau và tìm thấy những điều sau:
Wkhtmltopdf 0.12.2.1: Xấu
Wkhtmltopdf 0.12.3: Xấu
Wkhtmltopdf 0.12.1: Tốt
Giải pháp của tôi là hạ cấp xuống phiên bản 0.12.1, giải pháp này đã giải quyết được vấn đề của tôi. Đúng là, họ có thể một phần là do không quá OCD về html của tôi, nhưng vì HTML được tạo bên trong TinyMCE (bởi người dùng), tôi thực sự không có nhiều lựa chọn.
Ngoài ra, các bảng lồng nhau không hoạt động trong bất kỳ phiên bản nào đối với tôi.
Tôi đã đối mặt với cùng một vấn đề, thêm vào sau rất nhiều lần thử nghiệm n lỗi css này đã giải quyết được vấn đề
tr {
display: inline-table;
}
Làm thế nào để sử dụng ngắt trang bên trong pdf mà không ngắt tr?
Đây là giải pháp mà bạn có thể sử dụng trong bất kỳ tệp html nào .....
Sau khi bắt đầu tr, bạn phải lấy một div bên trong tr và đưa css này cho div:
<tr>
<div style="page-break-inside:avoid !important; page-break-after:auto !important; overflow: hidden; display:block !important; width:100% ">
</tr>
Với việc bổ sung những gì Nanotelep nói, đây là việc triển khai hoạt động của thuật toán ngắt trang bảng thủ công. https://github.com/AAverin/JSUtils/tree/master/wkhtmltopdfTableSplitHack
Các câu trả lời trên không làm việc với tôi. Tôi đã phải tắt cụ thể tùy chọn thu phóng mà cấu hình pdfkit của mình.
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
Đối với bất kỳ ai vẫn gặp vấn đề với điều này, một điều cần nhớ là bảng phải là con trực tiếp của body , nếu không css sẽ không hoạt động (ít nhất đó là những gì đã xảy ra với tôi).
display: table-cell;
áp dụng. Làm cho các kiểu đó @media only screen
cố định các ngắt trang. Nếu bạn không thể làm cho ngắt trang hoạt động, hãy cố gắng phân chia và chinh phục bằng cách loại bỏ một nửa CSS theo từng giai đoạn và xem liệu nó có hoạt động hay không.
Một tùy chọn khác: đặt từng cái tr
vào riêng của nó tbody
và sau đó áp dụng các quy tắc css của peage break cho tbody
. Bảng hỗ trợ nhiều tbody
s.
Một chút đánh dấu bổ sung, nhưng hiệu quả với tôi.
Tôi đã giải quyết vấn đề bằng cách sử dụng kết hợp một số giải pháp được đề xuất.
Tôi đã bọc bảng của mình trong một div và xác định CSS sau đây.
.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;
}
Cấu trúc bảng khi hoàn thành được định nghĩa như ví dụ sau:
<div class="wrapping-div">
<table>
<tbody>
<tr>
<th>
header
</th>
<td>
content
</td>
</tr>
</tbody>
</table>
</div>
Tôi không cần tạo bất kỳ div nào bên trong thẻ td hoặc th.
Những điều quan trọng mà tôi nhận thấy khi cố gắng giải quyết vấn đề:
Tôi hi vọng cái này giúp được.
Tôi đã phải vật lộn rất nhiều với vấn đề này, sử dụng h4cc / wkhtmltopdf-amd64 phiên bản 0.12.4 mới nhất và cuối cùng đã làm cho nó hoạt động bằng cách hạ cấp phiên bản của gói xuống 0.12.3
!
Để tránh ngắt trang, Chúng tôi có thể sử dụng tùy chọn css tránh ngắt trang.
tr { page-break-inside: avoid; }
Ngắt bất kỳ nội dung nào (Hình ảnh / Văn bản) và hiển thị nó ở trang tiếp theo
.sample-image { page-break-before: always; }
Bạn có đầu bảng không? và một thân bàn?
<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>
Đó là định dạng phù hợp của một bảng, trong khi hầu hết các trình duyệt không thể quan tâm hơn, các trình chuyển đổi như trình duyệt bạn đề cập có thể, nếu thiếu thẻ <tbody>
hoặc <th>
thẻ của bạn, tôi khuyên bạn nên thử thêm chúng trước.