Je génère un rapport pdf à partir d'une page html avec n tablea.
J'utilise wkhtmltopdf à cette fin.
quand pdf est généré, il casse n'importe où dans la balise tr.
Je veux l'éviter.
Mise à jour du 17.09.2015: Vérifiez la version que vous utilisez: wkhtmltopdf 0.12.2.4 est censé résoudre le problème (je n'ai pas vérifié) .
Ceci est un problème connu dans wkhtmltopdf. L'algorithme de coupure de page utilisé par webkit (le WK dans WKhtmltopdf) ne fonctionne pas vraiment pour les grands tableaux. Je suggère de réduire le tableau en de plus petits morceaux qui sont plus facilement scindés en pages et en utilisant le css beaucoup:
table, tr, td, th, tbody, thead, tfoot {
page-break-inside: avoid !important;
}
Jetez également un coup d'oeil aux problèmes suivants de wkhtmltopdf, ils ont des commentaires intéressants qui traitent par exemple du problème de fractionnement de table. Il existe une solution JS qui divise par programme les tables en 168 qui pourrait vous aider (je ne l’utilise pas cependant).
Mise à jour du 08.11.2013 Il y a beaucoup de discussions à ce sujet dans le numéro 168 lié ci-dessus. Quelqu'un a réussi à compiler une version de wkhtmltopdf qui prend en charge une meilleure décomposition des tables, mais malheureusement, il semble que celle-ci ne soit pas officiellement publiée et pourrait contenir d'autres bogues. Je ne sais pas comment l'obtenir et je ne sais pas comment compiler sous Windows, mais toute personne intéressée peut vérifier par exemple le commentaire ici (voir nouvelle mise à jour ci-dessous).
Mise à jour du 24.02.2014 Vous serez ravi d'apprendre que dans wkhtmltopdf 0.12, cette fonctionnalité, entre autres, a été grandement améliorée. Cependant, attendez 0.12.1 et testez bien avant d’utiliser une nouvelle version, c’est toujours un peu instable bien que les nouveaux gars travaillant avec antialize fassent un excellent travail (ashkulz rock)! Restez à jour à wkhtmltopdf.org et github . Le site de code google est obsolète et est en train de migrer lentement.
C'est un vieux message, mais comme je perdais beaucoup de temps à essayer de trouver la solution appropriée, 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 réalité, 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 la 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 cas un peu plus compliqué avec des rangées, donc la solution d'en haut consistait à la décomposer en morceaux, ce qui n'était pas l'effet recherché. Je l'ai résolu en utilisant divs pour chaque ligne de lignes. Mon jquery js fait tout le boulot:
$(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 ce soit parfait, mais cela fait le travail. Testé sur chrome seulement
Depuis la version 0.12, ce problème a été résolu, mais parfois, lorsqu'un tableau est trop long pour tenir dans la page, wkhtmltopdf le divise en deux parties et répète les en-têtes de colonne de la nouvelle page. Ces en-têtes de colonne apparaissent superposés à la première ligne.
J'ai trouvé une solution temporelle à ce problème dans la section des problèmes de github de wkhtmltopdf: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2531
Ajoutez simplement ces lignes à votre vue css:
tr {
page-break-inside: avoid;
}
J'ai trouvé que wkhtmltopdf 0.12.2.1 a résolu ce problème.
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 réalité une combinaison de plusieurs choses.
J'ai installé (dans Ubuntu 16.04) le Wkhtmltopdf python 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 à partir d'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 de ce CSS (comme suggéré dans l'une des réponses ici):
tr, td div, th div{
page-break-inside: avoid;
}
Et puis aussi ajoutez <thead>
et <tbody>
balises comme suggéré ici aussi (sans celles-ci, la table se casserait quand même d'une manière laide):
<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 modèles Mako pour générer le code HTML, puis le transmettre à Wkhtmltopdf et obtenir un fichier joliment paginé PDF :)
J'ai essayé toutes sortes de manipulations sur mes tables, mais rien de ce que j'ai essayé ne pouvait 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 trouvé ce qui suit:
Wkhtmltopdf 0.12.2.1: Mauvais
Wkhtmltopdf 0.12.3: Mauvais
Wkhtmltopdf 0.12.1: Bon
Ma solution a été de passer à la version 0.12.1, ce qui a résolu mes problèmes. Certes, ils sont peut-être dus en partie au fait que mon code HTML ne soit pas super OCD, mais comme le code HTML est généré dans TinyMCE (par les utilisateurs), je n'ai pas vraiment beaucoup de choix.
De plus, les tables imbriquées ne fonctionnent dans aucune version pour moi.
J'ai creusé ces problèmes pendant des jours et j'ai finalement trouvé la solution idéale. Vous pouvez référencer ce projet phpwkhtmltopdf . Regardez dans le répertoire article
et vous trouverez 3 solutions à 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, n'hésitez pas à consulter ce site wkhtmltopdf 定 一定 想 知道 这些 Consultez le Gist si vous le souhaitez Gist for wkhtmltopdf
Comment utiliser les sauts de page dans pdf sans casser une vérité?
Voici une solution que vous pouvez utiliser dans n’importe quel fichier html .....
Après avoir commencé votre tr, vous devez prendre une div à l’intérieur du tr et donner ce css au div:
<tr>
<div style="page-break-inside:avoid !important; page-break-after:auto !important; overflow: hidden; display:block !important; width:100% ">
</tr>
Je faisais face au même problème, ajoutons après beaucoup d’essais n erreurs ce css a résolu le problème
tr { display: inline-table; }
Pour ceux qui ont encore des problèmes avec cela, une chose à retenir est que le table doit être un enfant direct de body, sinon le css ne fonctionnera pas (du moins c'est que s'est-il passé avec moi).
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 la bonne mise en forme d’un tableau, alors que la plupart des navigateurs se moquent bien de convertisseurs comme celui que vous mentionnez pouvez, si vos balises <tbody>
ou <th>
manquantes, je vous suggère d'essayer de les ajouter en premier.
Avec l’ajout de ce que dit Nanotelep, voici l’implémentation fonctionnelle de l’algorithme manuel de rupture de page de table. https://github.com/AAverin/JSUtils/tree/master/wkhtmltopdfTableSplitHack
Les réponses ci-dessus ne m'ont pas fonctionné. Je devais désactiver spécifiquement l'option de 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
Une autre option: placez chaque tr
dans son propre tbody
, puis appliquez les règles css de rupture de peage à la tbody
. Les tables supportent plusieurs tbody
s.
Un peu de balisage supplémentaire, mais fonctionne décemment pour moi.
J'ai beaucoup lutté avec le problème, en utilisant la dernière version h4cc/wkhtmltopdf-AMD64 version 0.12.4 et enfin, nous avons réussi à le faire fonctionner en rétrogradant la version du paquet à 0.12.3
!
J'ai résolu le problème en utilisant une combinaison de 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é a été définie dans 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:
J'espère que ça aide.
J'ai trouvé cette solution ridicule, mais ça a très bien fonctionné pour moi :)
Je viens de mettre une très longue colonne rowspan comme celle-ci
<td rowspan="XXX TOTAL ROWS" style="width:0px"></td>
et alors la table ne se briserait pas.
Pour éviter un saut de page, nous pouvons utiliser l'option de saut de page pour éviter les CSS.
tr { page-break-inside: avoid; }
Casser n'importe quel contenu (Image/Texte) et le faire apparaître dans le page suivante
.sample-image { page-break-before: always; }