89 votes

Comment éviter le saut de page dans une ligne de tableau pour wkhtmltopdf ?

Je génère un rapport en pdf à partir d'une page html avec une table .

J'utilise wkhtmltopdf à cette fin.

lorsque le pdf est généré, il ruptures n'importe où dans la balise tr .

Je veux l'éviter.

166voto

Nenotlep Points 3432

Mise à jour 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é). .


C'est un problème connu dans wkhtmltopdf. L'algorithme de rupture de page utilisé par webkit (le WK de WKhtmltopdf) ne fonctionne pas vraiment bien pour les grands tableaux. Je suggère de décomposer le tableau 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 coup d'œil aux numéros suivants de wkhtmltopdf, ils contiennent des commentaires intéressants qui traitent par exemple du problème de la division des tableaux. Il existe une solution JS qui divise les tableaux de manière programmatique en 168, qui pourrait vous aider (je ne l'utilise pas cependant).

Mise à jour 08.11.2013 Il y a beaucoup de discussion à ce sujet dans le numéro 168 lié ci-dessus. Quelqu'un a réussi à compiler une version de wkhtmltopdf qui supporte une meilleure rupture de table, mais malheureusement il semble qu'elle n'est pas officiellement publiée et pourrait contenir d'autres bogues. Je ne sais pas comment l'obtenir et je ne sais pas comment la compiler sous Windows, mais toute personne intéressée peut consulter par exemple le commentaire suivant ici (voir la nouvelle mise à jour ci-dessous).

Mise à jour 24.02.2014 Vous serez heureux d'apprendre que dans wkhtmltopdf 0.12 cette fonctionnalité parmi d'autres a été grandement améliorée. Cependant, attendez la 0.12.1 et testez-la soigneusement avant de commencer à utiliser une nouvelle version, elle est encore un peu instable bien que les nouveaux gars qui travaillent avec antialize fassent un excellent travail (ashkulz rocks) ! Tenez vous au courant à wkhtmltopdf.org y github . Le site google code est obsolète et est en train de migrer lentement.

21voto

C'est un vieux message, mais comme je perdais beaucoup de temps à essayer de trouver une solution appropriée, je vais le mettre ici, peut-être qu'il sera utile à quelqu'un.

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 il fonctionne comme prévu (comme indiqué quelque part dans SO). donc pour une structure simple de table css avec

td div, th div{
    page-break-inside: avoid;
}

et la structure du tableau

<table>
....
<tr>
    <td><div>some text</div></td>
    <td><div>more text</div></td>
</tr>
....
</table>

fonctionnera comme prévu.

J'ai eu un cas un peu plus compliqué avec les rangées, donc la solution ci-dessus était de le décomposer en espaces, ce qui n'était pas l'effet désiré. J'ai résolu le problème en utilisant des divs pour chaque ensemble de lignes en interligne. 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 ce soit parfait, mais ça fait l'affaire. Testé sur chrome uniquement

19voto

Nacho Moço Points 380

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 coupe en deux parties et répète les en-têtes de colonnes sur la nouvelle page et ces en-têtes de colonnes apparaissent superposés à la première ligne.

J'ai trouvé une solution temporelle à ce problème sur la section wkhtmltopdf de github issues : https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2531

Ajoutez simplement ces lignes à votre css de vue :

tr {
  page-break-inside: avoid; 
}

9voto

UnixAgain Points 269

J'ai creusé ce problème pendant des jours, et j'ai 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, n'hésitez pas à consulter ce site wkhtmltopdf Consultez l'essentiel si vous le souhaitez Résumé pour wkhtmltopdf

5voto

Acapulco Points 391

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.

  1. J'ai installé (dans Ubuntu 16.04) le wrapper python de Wkhtmltopdf appelé pdfkit en utilisant pip3, et ensuite au lieu d'installer Wkhtmltopdf via apt-get j'ai installé le binaire statique (version 0.12.3) en suivant le script ci-dessous, tiré 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/
  2. J'ai ajouté ce CSS (comme suggéré dans une des réponses ici) :

    tr, td div, th div{
        page-break-inside: avoid;
    }
  3. Et puis también ajouter <thead> y <tbody> comme suggéré ici également (sans ces balises, le tableau se briserait encore de manière hideuse) :

    <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 HTML, puis le transmettre à Wkhtmltopdf et obtenir un PDF magnifiquement paginé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X