47 votes

Google Chrome répète les en-têtes de tableau sur les pages imprimées

J'aimerais que les en-têtes de mes tableaux soient répétés pour chaque page imprimée, mais il semble que Google Chrome ne prenne pas en charge l'option <thead> Est-ce qu'il y a un moyen de contourner ce problème ? J'utilise Google Chrome v13.0.782.215.

Le code de la table est très simple... rien d'extraordinaire :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <style type="text/css" media="all">
           @page {
              size: landscape;
              margin-top: 0;
              margin-bottom: 1cm;
              margin-left: 0;
              margin-right: 0;
           }
           table {
               border: .02em solid #666; border-collapse:collapse; 
               width:100%; 
           }
           td, th {
               border: .02em solid #666; font-size:12px; line-height: 12px; 
               vertical-align:middle; padding:5px; font-family:"Arial";
           }
           th { text-align:left; font-size:12px; font-weight:bold; }
           h2 { margin-bottom: 0; }
       </style>
   </head>
   <body>
   <h2>Page Title</h2>
   <table>
       <thead>
           <tr class="row1">
               <th><strong>Heading 1</strong></th>
               <th><strong>Heading 2</strong></th>
               <th><strong>Heading 3</strong></th>
               <th><strong>Heading 4</strong></th>
               <th><strong>Heading 5</strong></th>
           </tr>
       </thead>
       <tbody>
           <tr class="row2">
              <td width="30">...</td>
              <td width="30">...</td>
              <td width="90">....</td>
              <td width="190">...</td>
              <td width="420">...</td>
           </tr>
           <tr class="row1">
              <td width="30">...</td>
              <td width="30">...</td>
              <td width="90">....</td>
              <td width="190">...</td>
              <td width="420">...</td>
           </tr>
           ....
       </tbody>
   </table>
   </body>
</html>

Tout commentaire à ce sujet est le bienvenu.

53voto

DoctorDestructo Points 120

MISE À JOUR 2017-03-22 : Les en-têtes de tableau répétitifs ont enfin été implémentés dans Chrome ! (En fait, je pense qu'ils ont été implémentés il y a quelque temps.) Cela signifie que vous n'avez probablement plus besoin de cette solution ; mettez simplement vos en-têtes de colonne dans un fichier de type <thead> et vous devriez être prêt. N'utilisez la solution ci-dessous que si :

  • vous rencontrez des bogues dans l'implémentation de Chrome,
  • vous avez besoin des "bonus", ou
  • vous devez prendre en charge un navigateur bizarre qui ne prend toujours pas en charge les en-têtes répétitifs.

SOLUTION (obsolète)

Le code ci-dessous démontre la meilleure méthode que j'ai trouvée pour l'impression de tableaux multi-pages. Il présente les caractéristiques suivantes :

  • Les en-têtes de colonne se répètent sur chaque page
  • Vous n'avez pas à vous soucier de la taille du papier ou du nombre de lignes à insérer, le navigateur se charge de tout automatiquement.
  • Les sauts de page se produisent uniquement entre les rangées
  • Les bordures des cellules sont toujours entièrement fermées
  • Si un saut de page se produit près du haut du tableau, il ne laissera pas derrière lui une légende orpheline ou des en-têtes de colonne sans données (un problème qui n'est pas limité à Chrome).
  • Fonctionne dans Chrome ! (et d'autres navigateurs basés sur Webkit comme Safari et Opera)

... et les limitations connues suivantes :

  • Ne supporte que 1 <thead> (ce qui est apparemment le maximum que vous puissiez autorisé à avoir de toute façon)

  • Ne prend pas en charge <tfoot> (bien que les pieds de page compatibles avec Chrome soient techniquement possible )

  • Ne supporte que l'alignement en haut <caption>

  • La table ne peut pas avoir de haut ou de bas margin ; pour ajouter un espace blanc au-dessus ou au-dessous du tableau, insérez un div vide et définissez une marge inférieure sur celui-ci

  • Toute valeur de taille CSS qui affecte la hauteur (y compris border-width y line-height ) doit être dans px

  • La largeur des colonnes ne peut pas être définie en appliquant des valeurs de largeur aux cellules individuelles du tableau ; vous devez soit laisser le contenu des cellules déterminer automatiquement la largeur des colonnes, soit utiliser la commande <col>s pour définir des largeurs spécifiques si nécessaire

  • La table ne peut pas (facilement) être modifiée dynamiquement après l'exécution du JS.

LE CODE

<!DOCTYPE html>
<html>
  <body>
    <table class="print t1"> <!-- Delete "t1" class to remove row numbers. -->
      <caption>Print-Friendly Table</caption>
      <thead>
        <tr>
          <th></th>
          <th>Column Header</th>
          <th>Column Header</th>
          <th>Multi-Line<br/>Column<br/>Header</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td></td>
          <td>data</td>
          <td>Multiple<br/>lines of<br/>data</td>
          <td>data</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

<style>
  /* THE FOLLOWING CSS IS REQUIRED AND SHOULD NOT BE MODIFIED. */
    div.fauxRow {
      display: inline-block;
      vertical-align: top;
      width: 100%;
      page-break-inside: avoid;
    }
    table.fauxRow {border-spacing: 0;}
    table.fauxRow > tbody > tr > td {
      padding: 0;
      overflow: hidden;
    }
    table.fauxRow > tbody > tr > td > table.print {
      display: inline-table;
      vertical-align: top;
    }
    table.fauxRow > tbody > tr > td > table.print > caption {caption-side: top;}
    .noBreak {
      float: right;
      width: 100%;
      visibility: hidden;
    }
    .noBreak:before, .noBreak:after {
      display: block;
      content: "";
    }
    .noBreak:after {margin-top: -594mm;}
    .noBreak > div {
      display: inline-block;
      vertical-align: top;
      width:100%;
      page-break-inside: avoid;
    }
    table.print > tbody > tr {page-break-inside: avoid;}
    table.print > tbody > .metricsRow > td {border-top: none !important;}

  /* THE FOLLOWING CSS IS REQUIRED, but the values may be adjusted. */
    /* NOTE: All size values that can affect an element's height should use the px unit! */
    table.fauxRow, table.print {
      font-size: 16px;
      line-height: 20px;
    }

  /* THE FOLLOWING CSS IS OPTIONAL. */
    body {counter-reset: t1;} /* Delete to remove row numbers. */
    .noBreak .t1 > tbody > tr > :first-child:before {counter-increment: none;} /* Delete to remove row numbers. */
    .t1 > tbody > tr > :first-child:before { /* Delete to remove row numbers. */
      display: block;
      text-align: right;
      counter-increment: t1 1;
      content: counter(t1);
    }
    table.fauxRow, table.print {
      font-family: Tahoma, Verdana, Georgia; /* Try to use fonts that don't get bigger when printed. */
      margin: 0 auto 0 auto; /* Delete if you don't want table to be centered. */
    }
    table.print {border-spacing: 0;}
    table.print > * > tr > * {
      border-right: 2px solid black;
      border-bottom: 2px solid black;
      padding: 0 5px 0 5px;
    }
    table.print > * > :first-child > * {border-top: 2px solid black;}
    table.print > thead ~ * > :first-child > *, table.print > tbody ~ * > :first-child > * {border-top: none;}
    table.print > * > tr > :first-child {border-left: 2px solid black;}
    table.print > thead {vertical-align: bottom;}
    table.print > thead > .borderRow > th {border-bottom: none;}
    table.print > tbody {vertical-align: top;}
    table.print > caption {font-weight: bold;}
</style>

<script>
  (function() { // THIS FUNCTION IS NOT REQUIRED. It just adds table rows for testing purposes.
    var rowCount = 100
      , tbod = document.querySelector("table.print > tbody")
      , row = tbod.rows[0];
    for(; --rowCount; tbod.appendChild(row.cloneNode(true)));
  })();

  (function() { // THIS FUNCTION IS REQUIRED.
    if(/Firefox|MSIE |Trident/i.test(navigator.userAgent))
      var formatForPrint = function(table) {
        var noBreak = document.createElement("div")
          , noBreakTable = noBreak.appendChild(document.createElement("div")).appendChild(table.cloneNode())
          , tableParent = table.parentNode
          , tableParts = table.children
          , partCount = tableParts.length
          , partNum = 0
          , cell = table.querySelector("tbody > tr > td");
        noBreak.className = "noBreak";
        for(; partNum < partCount; partNum++) {
          if(!/tbody/i.test(tableParts[partNum].tagName))
            noBreakTable.appendChild(tableParts[partNum].cloneNode(true));
        }
        if(cell) {
          noBreakTable.appendChild(cell.parentNode.parentNode.cloneNode()).appendChild(cell.parentNode.cloneNode(true));
          if(!table.tHead) {
            var borderRow = document.createElement("tr");
            borderRow.appendChild(document.createElement("th")).colSpan="1000";
            borderRow.className = "borderRow";
            table.insertBefore(document.createElement("thead"), table.tBodies[0]).appendChild(borderRow);
          }
        }
        tableParent.insertBefore(document.createElement("div"), table).style.paddingTop = ".009px";
        tableParent.insertBefore(noBreak, table);
      };
    else
      var formatForPrint = function(table) {
        var tableParent = table.parentNode
          , cell = table.querySelector("tbody > tr > td");
        if(cell) {
          var topFauxRow = document.createElement("table")
            , fauxRowTable = topFauxRow.insertRow(0).insertCell(0).appendChild(table.cloneNode())
            , colgroup = fauxRowTable.appendChild(document.createElement("colgroup"))
            , headerHider = document.createElement("div")
            , metricsRow = document.createElement("tr")
            , cells = cell.parentNode.cells
            , cellNum = cells.length
            , colCount = 0
            , tbods = table.tBodies
            , tbodCount = tbods.length
            , tbodNum = 0
            , tbod = tbods[0];
          for(; cellNum--; colCount += cells[cellNum].colSpan);
          for(cellNum = colCount; cellNum--; metricsRow.appendChild(document.createElement("td")).style.padding = 0);
          cells = metricsRow.cells;
          tbod.insertBefore(metricsRow, tbod.firstChild);
          for(; ++cellNum < colCount; colgroup.appendChild(document.createElement("col")).style.width = cells[cellNum].offsetWidth + "px");
          var borderWidth = metricsRow.offsetHeight;
          metricsRow.className = "metricsRow";
          borderWidth -= metricsRow.offsetHeight;
          tbod.removeChild(metricsRow);
          tableParent.insertBefore(topFauxRow, table).className = "fauxRow";
          if(table.tHead)
            fauxRowTable.appendChild(table.tHead);
          var fauxRow = topFauxRow.cloneNode(true)
            , fauxRowCell = fauxRow.rows[0].cells[0];
          fauxRowCell.insertBefore(headerHider, fauxRowCell.firstChild).style.marginBottom = -fauxRowTable.offsetHeight - borderWidth + "px";
          if(table.caption)
            fauxRowTable.insertBefore(table.caption, fauxRowTable.firstChild);
          if(tbod.rows[0])
            fauxRowTable.appendChild(tbod.cloneNode()).appendChild(tbod.rows[0]);
          for(; tbodNum < tbodCount; tbodNum++) {
            tbod = tbods[tbodNum];
            rows = tbod.rows;
            for(; rows[0]; tableParent.insertBefore(fauxRow.cloneNode(true), table).rows[0].cells[0].children[1].appendChild(tbod.cloneNode()).appendChild(rows[0]));
          }
          tableParent.removeChild(table);
        }
        else
          tableParent.insertBefore(document.createElement("div"), table).appendChild(table).parentNode.className="fauxRow";
      };
    var tables = document.body.querySelectorAll("table.print")
      , tableNum = tables.length;
    for(; tableNum--; formatForPrint(tables[tableNum]));
  })();
</script>

COMMENT ÇA MARCHE (Si vous ne vous en souciez pas, ne lisez pas plus loin ; tout ce dont vous avez besoin se trouve ci-dessus).

À la demande de @Kingsolmn, vous trouverez ci-dessous une explication du fonctionnement de cette solution. Elle ne couvre pas le JavaScript, qui n'est pas strictement nécessaire (bien qu'il rende cette technique beaucoup plus facile à utiliser). Elle se concentre plutôt sur les structures HTML générées et les CSS associées, où la vraie magie opère.

Voici la table avec laquelle nous allons travailler :

<table>
  <tr><th>ColumnA</th><th>ColumnB</th></tr>
  <tr><td>row1</td><td>row1</td></tr>
  <tr><td>row2</td><td>row2</td></tr>
  <tr><td>row3</td><td>row3</td></tr>
</table>

(Pour économiser de l'espace, je n'ai donné que 3 lignes de données ; évidemment, un tableau de plusieurs pages en aurait généralement plus).

La première chose à faire est de diviser le tableau en une série de tableaux plus petits, chacun ayant sa propre copie des en-têtes de colonne. J'appelle ces petits tableaux fausses rangées .

<table> <!-- fauxRow -->
  <tr><th>ColumnA</th><th>ColumnB</th></tr>
  <tr><td>row1</td><td>row1</td></tr>
</table>

<table> <!-- fauxRow -->
  <tr><th>ColumnA</th><th>ColumnB</th></tr>
  <tr><td>row2</td><td>row2</td></tr>
</table>

<table> <!-- fauxRow -->
  <tr><th>ColumnA</th><th>ColumnB</th></tr>
  <tr><td>row3</td><td>row3</td></tr>
</table>

Les fausses lignes sont essentiellement des clones de la table originale, mais avec une seule ligne de données par ligne. (Si votre tableau comporte une légende, cependant, seule la fausse rangée supérieure doit l'inclure).

Ensuite, nous devons créer les faux rangs incassable . Qu'est-ce que cela signifie ? (Faites attention - c'est probablement le concept le plus important dans la gestion des sauts de page). "Insécable" est le terme que j'utilise pour décrire un bloc de contenu qui ne peut pas être divisé entre deux pages*. Lorsqu'un saut de page se produit dans l'espace occupé par un tel bloc, l'ensemble du bloc passe à la page suivante. (Notez que j'utilise le mot "bloc" de manière informelle ici ; je suis no se référant spécifiquement à éléments au niveau du bloc .) Ce comportement a un effet secondaire intéressant que nous utiliserons plus tard : il peut exposer le contenu qui était initialement caché en raison de la superposition ou du débordement.

Nous pouvons rendre les fausses rangées insécables en appliquant l'une des déclarations CSS suivantes :

  • page-break-inside: avoid;
  • display: inline-table;

J'utilise généralement les deux, car le premier est conçu à cet effet et le second fonctionne dans les navigateurs anciens/non conformes. Dans ce cas, cependant, pour des raisons de simplicité, je m'en tiendrai à la propriété "page-break". Notez que vous ne verrez aucun changement dans l'apparence du tableau après avoir ajouté cette propriété.

<table style="page-break-inside: avoid;"> <!-- fauxRow -->
      <tr><th>ColumnA</th><th>ColumnB</th></tr>
      <tr><td>row1</td><td>row1</td></tr>
    </table>

    <table style="page-break-inside: avoid;"> <!-- fauxRow -->
      <tr><th>ColumnA</th><th>ColumnB</th></tr>
      <tr><td>row2</td><td>row2</td></tr>
    </table>

    <table style="page-break-inside: avoid;"> <!-- fauxRow -->
      <tr><th>ColumnA</th><th>ColumnB</th></tr>
      <tr><td>row3</td><td>row3</td></tr>
    </table>

Maintenant que les fauxRows sont insécables, si un saut de page se produit dans une ligne de données, celle-ci passera à la page suivante avec la ligne d'en-tête qui lui est attachée. Ainsi, la page suivante aura toujours des en-têtes de colonne en haut, ce qui est notre objectif. Mais le tableau a maintenant un aspect très étrange avec toutes ces lignes d'en-tête supplémentaires. Pour qu'il ressemble à nouveau à un tableau normal, nous devons masquer les en-têtes supplémentaires de manière à ce qu'ils n'apparaissent qu'en cas de besoin.

Ce que nous allons faire, c'est mettre chaque fausse rangée dans un élément conteneur avec overflow: hidden; puis le décaler vers le haut pour que les en-têtes soient coupés par le haut du conteneur. Cela permettra également de rapprocher les lignes de données afin qu'elles apparaissent contiguës.

Votre premier réflexe pourrait être d'utiliser des divs pour les conteneurs, mais nous allons plutôt utiliser les cellules d'un tableau parent. J'expliquerai pourquoi plus tard, mais pour l'instant, ajoutons simplement le code. (Encore une fois, cela n'affectera pas l'apparence de la table).

table {
  border-spacing: 0;
  line-height: 20px;
}
th, td {
  padding-top: 0;
  padding-bottom: 0;
}

<table> <!-- parent table -->
  <tr>
    <td style="overflow: hidden;">

      <table style="page-break-inside: avoid;"> <!-- fauxRow -->
        <tr><th>ColumnA</th><th>ColumnB</th></tr>
        <tr><td>row1</td><td>row1</td></tr>
      </table>

    </td>
  </tr>
  <tr>
    <td style="overflow: hidden;">

      <table style="page-break-inside: avoid;"> <!-- fauxRow -->
        <tr><th>ColumnA</th><th>ColumnB</th></tr>
        <tr><td>row2</td><td>row2</td></tr>
      </table>

    </td>
  </tr>
  <tr>
    <td style="overflow: hidden;">

      <table style="page-break-inside: avoid;"> <!-- fauxRow -->
        <tr><th>ColumnA</th><th>ColumnB</th></tr>
        <tr><td>row3</td><td>row3</td></tr>
      </table>

    </td>
  </tr>
</table>

Remarquez le CSS au-dessus de la table de balisage. Je l'ai ajouté pour deux raisons : premièrement, il empêche la table parente d'ajouter des espaces blancs entre les fausses lignes ; deuxièmement, il rend la hauteur de l'en-tête prévisible, ce qui est nécessaire puisque nous n'utilisons pas JavaScript pour la calculer dynamiquement.

Il ne nous reste plus qu'à décaler les fauxRows vers le haut, ce que nous ferons avec des marges négatives. Mais ce n'est pas aussi simple qu'on pourrait le croire. Si nous ajoutons une marge négative directement à une fausse rangée, elle restera en vigueur lorsque la fausse rangée passera à la page suivante, ce qui aura pour effet d'écrêter les en-têtes par rapport au haut de la page. Nous devons trouver un moyen de laisser la marge négative derrière nous.

Pour ce faire, nous allons insérer un div vide au-dessus de chaque fausse rangée après la première et lui ajouter la marge négative. (La première fausse rangée est ignorée car ses en-têtes doivent toujours être visibles). Comme la marge se trouve sur un élément distinct, elle ne suivra pas la fausse rangée sur la page suivante et les en-têtes ne seront pas coupés. J'appelle ces divs vides headerHiders .

table {
  border-spacing: 0;
  line-height: 20px;
}
th, td {
  padding-top: 0;
  padding-bottom: 0;
}

<table> <!-- parent table -->
  <tr>
    <td style="overflow: hidden;">

      <table style="page-break-inside: avoid;"> <!-- fauxRow -->
        <tr><th>ColumnA</th><th>ColumnB</th></tr>
        <tr><td>row1</td><td>row1</td></tr>
      </table>

    </td>
  </tr>
  <tr>
    <td style="overflow: hidden;">

      <div style="margin-bottom: -20px;"></div> <!-- headerHider -->

      <table style="page-break-inside: avoid;"> <!-- fauxRow -->
        <tr><th>ColumnA</th><th>ColumnB</th></tr>
        <tr><td>row2</td><td>row2</td></tr>
      </table>

    </td>
  </tr>
  <tr>
    <td style="overflow: hidden;">

      <div style="margin-bottom: -20px;"></div> <!-- headerHider -->

      <table style="page-break-inside: avoid;"> <!-- fauxRow -->
        <tr><th>ColumnA</th><th>ColumnB</th></tr>
        <tr><td>row3</td><td>row3</td></tr>
      </table>

    </td>
  </tr>
</table>

C'est ça, on a fini ! À l'écran, le tableau devrait maintenant avoir un aspect normal, avec un seul ensemble d'en-têtes de colonne en haut. À l'impression, il devrait maintenant avoir des en-têtes courants.

Si vous vous demandez pourquoi nous avons utilisé un tableau parent au lieu d'un ensemble de divs conteneurs, c'est parce que Chrome/webkit a un bug qui fait qu'un bloc insécable entouré de divs emporte son conteneur avec lui sur la page suivante. Comme le headerHider se trouve également dans le conteneur, il ne sera pas laissé derrière comme il est censé l'être, ce qui entraîne des en-têtes coupés. Ce bogue ne se produit que si le bloc insécable est l'élément le plus haut dans le div avec une hauteur non nulle.

J'ai découvert une solution de contournement lors de l'écriture de ce tutoriel : il suffit de définir explicitement le paramètre height: 0; sur le headerHider et lui donner un div enfant vide avec une hauteur non nulle. Vous pouvez ensuite utiliser un conteneur div. Je préfère cependant utiliser une table parente, parce qu'elle a été testée de manière plus approfondie et qu'elle permet de sauver la sémantique dans une certaine mesure en reliant les faux rangs en une seule table.

EDITAR: Je viens de réaliser que le balisage généré par JavaScript est légèrement différent dans la mesure où il place chaque fausse rangée dans un tableau conteneur séparé, et lui attribue le className "fauxRow" (le conteneur). Cela serait nécessaire pour le support du pied de page, que j'avais l'intention d'ajouter un jour mais que je n'ai jamais fait. Si je devais mettre à jour le JS, je pourrais envisager de passer à des conteneurs div puisque ma justification sémantique pour l'utilisation d'une table ne s'applique pas.

* Il y a une situation dans laquelle un bloc incassable peut être réparti sur deux pages : lorsqu'il dépasse la hauteur de la zone imprimable. Vous devriez essayer d'éviter ce scénario ; vous demandez essentiellement au navigateur de faire l'impossible, et cela peut avoir des effets très étranges sur la sortie.

40voto

Arif Uddin Points 416

Je crois que c'est un bogue en Chrome.

4voto

thefredzx Points 41

Maintenant il est possible d'imprimer dans chrome en utilisant jQuery.... s'il vous plaît essayez ce code (je suis désolé d'oublier qui est le créateur de ce code avant que je modifie - et ma langue anglaise n'est pas bon :D hehehe)

            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <html>
            <head>
                <title>DOCUMENT TITLE</title>
                <link rel="stylesheet" type="text/css" href="assets/css/bootstrap.css"/>
                <style type="text/css">
                    @media print{
                        table { page-break-after:auto;}
                        tr    { page-break-inside:avoid;}
                        td    { page-break-inside:auto;}
                        thead { display:table-header-group }

                        .row-fluid [class*="span"] {
                          min-height: 20px;
                        }
                    }

                    @page { 
                        margin-top: 1cm;
                        margin-right: 1cm;
                        margin-bottom:2cm;
                        margin-left: 2cm;';
                        size:portrait;
                        /*
                        size:landscape;
                        -webkit-transform: rotate(-90deg); -moz-transform:rotate(-90deg);
                        filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
                        */

                    };
                </style>
            </head>
            <body>
                <div id="print-header-wrapper">
                    <div class="row-fluid">HEADER TITLE 1</div>
                    <div class="row-fluid">HEADER TITLE 2</div>
                </div>
                <div class="row-fluid" id="print-body-wrapper">
                    <table class="table" id="table_data">
                        <thead>
                            <tr><th>TH 1</th><th>TH 2</th></tr>
                        </thead>
                        <tbody>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                            <tr><td>TD 1</td><td>TD 2</td></tr>
                        </tbody>
                    </table>
                    <div id="lastDataTable"></div>
                </div>
                <script type="text/javascript">
                    jQuery(document).ready(function()
                    {
                        var printHeader = $('#print-header-wrapper').html();
                        var div_pageBreaker = '<div style="page-break-before:always;"></div>';
                        var per_page = 25;
                        $('#table_data').each(function(index, element)
                        {
                            //how many pages of rows have we got?
                            var pages = Math.ceil($('tbody tr').length / per_page);

                            //if we only have one page no more
                            if (pages == 1) {
                                return;
                            }
                            //get the table we're splutting
                            var table_to_split = $(element);

                            var current_page   = 1;
                            //loop through each of our pages
                            for (current_page = 1; current_page <= pages; current_page++) 
                            {
                                //make a new copy of the table
                                var cloned_table = table_to_split.clone();
                                //remove rows on later pages
                                $('tbody tr', table_to_split).each(function(loop, row_element) {
                                    //if we've reached our max
                                    if (loop >= per_page) {
                                        //get rid of the row
                                        $(row_element).remove();
                                    }
                                });

                                //loop through the other copy
                                $('tbody tr', cloned_table).each(function(loop, row_element) {
                                    //if we are before our current page
                                    if (loop < per_page) {
                                        //remove that one
                                        $(row_element).remove();
                                    }
                                });

                                //insert the other table afdter the copy
                                if (current_page < pages) {
                                    $(div_pageBreaker).appendTo('#lastDataTable');
                                    $(printHeader).appendTo('#lastDataTable');
                                    $(cloned_table).appendTo('#lastDataTable');
                                }

                                //make a break
                                table_to_split = cloned_table;
                            }
                        });
                    });
                </script>
              </body>
            </html>

2voto

user1920145 Points 13

Il s'agit d'une amélioration qui n'est toujours pas disponible dans Webkit, Blink et Vivliostyle, plutôt que dans d'autres formateurs plus "orientés impression" (Firefox, IE).

Vous pouvez vérifier le problème pour Google Chrome depuis la version 4 ici (il y a 6 ans et 45 versions !) où l'on peut apprécier qu'il a un propriétaire depuis peu (février 2016), qui semble même y travailler.

Certains parlent a également été retenu dans le W3 où nous pouvons apprécier l'inquiétude sur son utilité :

Étant donné que la répétition des en-têtes et des pieds de tableau sur une fragmentation est généralement une chose utile, je suggère que nous fassions une exigence normative et de dire que les UA doivent répéter les lignes d'en-tête et de pied de page lorsqu'un tableau s'étend sur une coupure.

En attendant, les codes JS et Jquery de @DoctorDestructo et @thefredzx ont été très utiles pour mes utilisateurs n'utilisant ni Firefox ni IE (la plupart d'entre eux).

Le premier à être au courant d'une nouvelle version qui inclut cette fonctionnalité, devrait le signaler ici, beaucoup d'entre nous l'apprécieraient.

1voto

ak85 Points 3616

D'après mes tests dans les paramètres de chrome display: table-row-group; à la théade empêche le problème de se produire.

Par exemple, si vous essayez d'imprimer le document ci-dessous sans le style, vous verrez le numéro en haut de chaque page, mais si vous ajoutez le style, il n'apparaît que dans le menu contextuel.

<style>
  thead {
      display: table-row-group;
  }
</style>
<table>
  <thead>
    <tr>
      <th>number</th>
    </tr>
  </thead>
  <tbody id="myTbody">
  </tbody>
</table>
<script>
  for (i = 1; i <= 100; i++) {
    document.getElementById("myTbody").innerHTML += "<tr><td>" + i + "</td></tr>";
  }
</script>

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