Comment éviter le saut de page dans la ligne de la table pour wkhtmltopdf
Je génère un rapport pdf à partir d'une page html avec une table.
J'utilise wkhtmltopdf dans le but.
Lorsque le pdf est généré, il se casse n'importe où dans la balise tr.
Je veux l'éviter .
17 réponses
Mise à Jour 17.09.2015: Vérifier la version que vous utilisez: wkhtmltopdf 0.12.2.4 est dit pour résoudre le problème (je n'ai pas vérifié).
C'est un problème connu dans wkhtmltopdf. L'algorithme de rupture de page utilisé par webkit (le WK dans WKhtmltopdf) ne fonctionne pas vraiment bien pour les grandes tables. Je suggère de diviser la table en petits morceaux qui sont plus facilement divisés en pages et d'utiliser beaucoup le css:
table, tr, td, th, tbody, thead, tfoot {
page-break-inside: avoid !important;
}
Jetez également un oeil aux problèmes wkhtmltopdf suivants, ils ont des commentaires intéressants qui discutent par exemple du problème de division de table. Il existe une solution JS qui divise par programmation les tables en 168 qui pourrait vous aider (Je ne l'utilise pas cependant).
- https://code.google.com/p/wkhtmltopdf/issues/detail?id=168
- https://code.google.com/p/wkhtmltopdf/issues/detail?id=9
Mise à Jour 08.11.2013
Il y a beaucoup de discussions à ce sujet dans la question 168 liée ci-dessus. Quelqu'un a réussi à compilez une version de wkhtmltopdf qui prend en charge une meilleure rupture de table, mais malheureusement, il semble qu'elle ne soit pas officiellement publiée et puisse contenir d'autres bogues. Je ne sais pas comment l'obtenir et je ne sais pas comment compiler sur Windows, mais toute personne intéressée peut vérifier par exemple le commentaire tiens (voir la nouvelle mise à jour ci-dessous).
Mise à Jour 24.02.2014 Vous serez heureux d'apprendre que dans wkhtmltopdf 0.12 cette fonction, entre autres, a été grandement améliorée. Cependant, attendez pour 0.12.1 et tester soigneusement avant de commencer à utiliser une nouvelle version, c'est toujours un peu instable bien que les nouveaux gars qui travaillent avec antialize font un excellent travail (ashkulz rocks)! Tenir à jour à wkhtmltopdf.org et github. Le site de code google est obsolète et en cours de migration lente.
C'est un ancien post, mais comme je perdais beaucoup de temps à essayer de trouver la bonne solution, je vais le mettre ici, peut-être que ce sera utile à quelqu'un.
Donc, d'après ce que j'ai lu, le problème avec
page-break-inside: avoid
C'est que ça ne marche pas. Mais en fait, si vous le définissez sur un élément qui a display:block
, cela fonctionne comme prévu (comme indiqué quelque part dans SO).
donc, pour une structure simple de la table css avec
td div, th div{
page-break-inside: avoid;
}
Et la structure de la table
<table>
....
<tr>
<td><div>some text</div></td>
<td><div>more text</div></td>
</tr>
....
</table>
Fonctionnera comme prévu.
J'avais un peu plus cas compliqué avec rowspans, donc la solution d'en haut était de le briser en paix, ce qui n'était pas l'effet désiré. Je l'ai résolu en utilisant divs pour chaque ensemble de lignes rowspaned. Mon jquery Js fait tout le travail:
$(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;
}
Je ne sais pas si tout est nécessaire et je ne pense pas que c'est parfait, mais ça fait le travail. Testé sur chrome uniquement
Depuis 0.12 ce problème a été résolu mais, parfois, quand une table est trop longue pour tenir dans la page, wkhtmltopdf le brise en deux parties et répète les en-têtes de colonne sur la nouvelle page et ces en-têtes de colonne apparaissent superposés à la première ligne.
J'ai trouvé une solution temporelle à ce problème sur la section Problèmes de wkhtmltopdf github: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2531
Ajoutez simplement ces lignes à votre vue css:
tr {
page-break-inside: avoid;
}
Dans mon cas particulier, pour une raison quelconque, aucune des réponses précédentes n'a fonctionné pour moi. Ce qui a fini par fonctionner était en fait une combinaison de plusieurs choses.
-
J'ai installé (dans Ubuntu 16.04) le wrapper python wkhtmltopdf appelé pdfkit en utilisant pip3, puis au lieu d'installer Wkhtmltopdf via apt-get j'ai installé le binaire statique (version 0.12.3) en suivant le script ci-dessous, pris ici
#!/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/
-
Ajouté ce CSS (comme suggéré dans l'une des réponses ici):
tr, td div, th div{ page-break-inside: avoid; }
-
, puis aussi ajouter
<thead>
et<tbody>
balises comme suggéré ici (sans ces le tableau serait encore pause dans un laid sens):<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>
Avec ces modifications, je peux maintenant utiliser avec succès Mako templates pour générer le HTML, puis le transmettre à Wkhtmltopdf et obtenir un PDF magnifiquement paginé:)
J'ai essayé toutes sortes de manipulations sur mes tables, mais rien de ce que j'ai essayé n'a pu empêcher les sauts de page d'être placés au milieu d'une rangée. En désespoir de cause, j'ai essayé différentes versions, et j'ai trouvé ce qui suit:
Wkhtmltopdf 0.12.2.1: Mauvais
Wkhtmltopdf 0.12.3: Mauvais
Wkhtmltopdf 0.12.1: Bon
Ma solution était de rétrograder à la version 0.12.1, ce qui a résolu mes problèmes. Certes, ils auraient pu être en partie dus à ne pas être super TOC à propos de mon html, mais comme le HTML est généré à L'intérieur de TinyMCE (par les utilisateurs) je n'ai pas vraiment beaucoup de choix.
En outre, les tables imbriquées ne fonctionnent dans aucune version pour moi.
Comment utiliser les sauts de page à l'intérieur de pdf sans casser un tr?
Voici une solution que vous pouvez utiliser dans n'importe quel fichier html.....
Après avoir démarré votre tr, vous devez prendre un div dans le tr et donner ce css à la div:
<tr>
<div style="page-break-inside:avoid !important; page-break-after:auto !important; overflow: hidden; display:block !important; width:100% ">
</tr>
Avez-vous une tête de table? et un corps de table?
<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>
C'est le formatage correct d'une table, alors que la plupart des navigateurs s'en fichent, convertisseurs comme celui que vous mentionnez, si vos balises <tbody>
ou <th>
manquantes, je vous suggère d'essayer d'ajouter celles-ci en premier.
En plus de ce que dit Nanotelep, voici l'implémentation de travail de l'algorithme de rupture de page de table manuelle. https://github.com/AAverin/JSUtils/tree/master/wkhtmltopdfTableSplitHack
Les réponses ci-dessus n'ont pas fonctionné pour moi. J'ai dû désactiver spécifiquement l'option zoom de ma configuration 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
Pour tous ceux qui ont encore des problèmes avec cela, une chose à retenir est que la table doit être un enfant direct de body , sinon le css ne fonctionnera pas (du moins c'est ce qui s'est passé avec moi).
J'ai trouvé cette solution ridicule, mais cela a très bien fonctionné pour moi :)
Je viens de mettre une très longue colonne rowspan comme ceci
<td rowspan="XXX TOTAL ROWS" style="width:0px"></td>
Et alors la table ne se casserait pas.
Une autre option: placez chaque tr
dans son propre tbody
, puis appliquez les règles CSS Peage break au tbody
. Les Tables prennent en charge Plusieurs tbody
s.
Un peu de balisage, mais fonctionne décemment pour moi.
J'étais confronté au même problème ajouter après beaucoup d'erreurs d'essai n Ce css a résolu le problème
tr {
display: inline-table;
}
J'ai creusé dans ce problème pendant des jours, et finalement trouvé la solution parfaite. Vous pouvez référencer ce projet phpwkhtmltopdf . Regardez dans le répertoire article
et vous trouverez 3 solutions pour 3 problèmes.
En bref, la solution ultime est d'ajouter le style 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;
}
Si vous êtes Chinois, sentez-vous libre pour vérifier ce site 关于wkhtmltopdf 你 你一这这这 Découvrez l'essentiel si vous souhaitez résumé de wkhtmltopdf
J'ai résolu le problème en utilisant une combinaison de quelques solutions suggérées.
J'ai enveloppé ma table dans un div et défini le CSS suivant.
.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;
}
La structure de la table une fois terminée a été définie comme l'exemple suivant:
<div class="wrapping-div">
<table>
<tbody>
<tr>
<th>
header
</th>
<td>
content
</td>
</tr>
</tbody>
</table>
</div>
Je n'avais pas besoin de créer de div à l'intérieur des balises td ou th.
Choses importantes que j'ai remarquées en essayant de résoudre le problème:
- le tbody doit être inclus dans le tableau
- le div doit avoir un affichage: bloc
- Quand une table ne rentre pas dans une page, elle déplace automatiquement toute la table vers la page suivante (je n'ai pas essayé celle-ci avec des tables énormes)
- Si vous supprimez uniquement le ".wrapping-div table " sélecteur à partir du CSS, Il permettra à la table d'être divisée en deux pages, mais la rendra correctement, ne cassant pas une cellule en deux pages (c'est comme le comportement par défaut sur Word)
J'espère que cela aide.
J'ai beaucoup lutté avec le problème, en utilisant la dernière version h4cc/wkhtmltopdf-amd64 0.12.4 et finalement l'a fait fonctionner en rétrogradant la version du paquet à 0.12.3
!