Tableau pleine page TCPDF

11

J'ai essayé de nombreuses façons d'adapter le tableau à la page (A4) comme indiqué sur l'image: entrez la description de l'image ici j'ai beaucoup cherché mais je n'ai rien trouvé d'utile sur le web. J'utilise une table dynamique, tout va bien sauf la largeur de la table. voici mon code:

$content = '<table><thead><tr><th class="bg-dark text-white" align="center">#</th><th align="center" class="bg-dark text-white">Code</th><th align="left" class="bg-dark text-white">Description</th><th align="center" class="bg-dark text-white">Item Type</th></tr></thead><tbody><tr style="background-color: #f2f2f2;"><td align="center">1</td><td align="center">1001</td><td align="left">Pofak</td><td align="center">Fixed Price</td></tr><tr ><td align="center">2</td><td align="center">1002</td><td align="left">Ice</td><td align="center">Weight</td></tr><tr style="background-color: #f2f2f2;"><td align="center">3</td><td align="center">1003</td><td align="left">Minoo</td><td align="center">Fixed Price</td></tr><tr ><td align="center">4</td><td align="center">1004</td><td align="left">Bastani</td><td align="center">Fixed Price</td></tr><tr style="background-color: #f2f2f2;"><td align="center">5</td><td align="center">1005</td><td align="left">Chocolate</td><td align="center">Weight</td></tr><tr ><td align="center">6</td><td align="center">1006</td><td align="left">Brush</td><td align="center">Fixed Price</td></tr><tr style="background-color: #f2f2f2;"><td align="center">7</td><td align="center">1007</td><td align="left">Apple</td><td align="center">Weight</td></tr><tr ><td align="center">8</td><td align="center">1008</td><td align="left">Water</td><td align="center">Fixed Price</td></tr><tr style="background-color: #f2f2f2;"><td align="center">9</td><td align="center">1009</td><td align="left">Cleaner</td><td align="center">Fixed Price</td></tr><tr ><td align="center">10</td><td align="center">1001</td><td align="left">Pofak</td><td align="center">Fixed Price</td></tr><tr style="background-color: #f2f2f2;"><td align="center">11</td><td align="center">1002</td><td align="left">Ice</td><td align="center">Weight</td></tr><tr ><td align="center">12</td><td align="center">1003</td><td align="left">Minoo</td><td align="center">Fixed Price</td></tr><tr style="background-color: #f2f2f2;"><td align="center">13</td><td align="center">1004</td><td align="left">Bastani</td><td align="center">Fixed Price</td></tr><tr ><td align="center">14</td><td align="center">1005</td><td align="left">Chocolate</td><td align="center">Weight</td></tr><tr style="background-color: #f2f2f2;"><td align="center">15</td><td align="center">1006</td><td align="left">Brush</td><td align="center">Fixed Price</td></tr></tbody></table>';
$newContent = '
    <style type="text/css">
    table{width:100%;}
    table, table td, table th{
        border-collapse: collapse;
        border: solid 1px #ababab;
    }
    .text-dark, table td{
        color: #343a40;
    }
    .text-white{
        color: #ffffff;
    }
    table td,
    table th {
        font-size: 11px;
        padding: 3px;
        line-height: 1.2;
        font-family:arial;
    }

    .bg-dark {
        background-color: #343a40;
    }
    .bg-secondary {
        background-color: #6c757d;
    }
    .bg-white {
        background-color: #ffffff;
    }
    .text-left {
        text-align: left;
    }
    .text-right {
        text-align: right;
    }
    .text-center {
        text-align: center;
    }
    </style>
    ';
    $newContent .= '<page>'.$content.'</page>';

    try {
        $html2pdf = new Html2Pdf('P', 'A4', 'en', true, 'UTF-8', 5);
        $html2pdf->pdf->SetDisplayMode('real');
        $html2pdf->writeHTML($newContent);
        $PDFName = "ItemLists_".date('Y.m.d_H.i.s').".pdf";
        $html2pdf->output($PDFName, 'I');
    } catch (Html2PdfException $x) {
        $html2pdf->clean();

        $formatter = new ExceptionFormatter($x);
        echo $formatter->getHtmlMessage();
    }

Merci beaucoup

Mohsen Newtoa
la source
Il s'agit en fait d'un bogue dans la bibliothèque Html2PDF. Recherche d'une solution de contournement potentielle.
EPB
Il convient de noter, btw, que Html2PDF utilise son propre analyseur HTML. style="width: 100%"stocke la largeur correctement convertie en MM (bien que l'attribut width ne le fasse pas!) Cependant Html2PDF ne semble pas l'utiliser réellement pendant le rendu de la table.
EPB

Réponses:

4

Html2PDF n'utilise pas le système d'analyseur / rendu HTML de TCPDF. Il implémente le sien, et son implémentation n'augmente pas automatiquement les colonnes pour remplir 100% de l'espace.

En tant que tel, dans Html2PDF, non seulement vous devez définir une largeur de 100% sur la table, mais vous devez définir des largeurs en pourcentage pour chacune des cellules. (Et en raison d'un comportement étrange avec l' widthattribut dans Html2PDF, utilisez CSS pour définir les largeurs.)

Le natif de TCPDF writeHTMLdéfinira chaque colonne sur la même largeur en l'absence de toute autre spécification. (Par exemple, un tableau à 4 colonnes a toutes les cellules à 25%) Cependant, il ne prend pas en charge le CSS que vous utilisez, donc le balisage nécessiterait un petit ajustement pour suivre cette voie.

Pour imiter ce comportement de base dans Html2PDF, vous pouvez simplement ajouter explicitement des largeurs équivalentes à vos cellules. Par exemple, ajouter une spécification de largeur à vos table td, table thrègles de style.

Voici un exemple avec les règles CSS suivantes pour une table à quatre colonnes:

table { width: 100%; }
table th, table td { width: 25%; }

Bien sûr, cela semble mieux lorsque vous spécifiez des largeurs qui correspondent à votre contenu.

Exemple avec des colonnes équivalentes


MISE À JOUR

Je vais laisser une partie de la discussion sur TCPDF ci-dessous car elle conduit quelque peu à la création d'une classe potentiellement utile pour Html2pdf. TCPDF a quelques méthodes utiles pour mesurer la longueur d'une chaîne. Si vous mesurez la taille des chaînes à l'intérieur des colonnes, vous pouvez créer votre propre dimensionneur de colonne automatique.

J'ai créé une classe de preuve de concept sur github à https://github.com/b65sol/random-classes

Tout d'abord, nous utilisons la classe pour arbitrer la construction du HTML. C'est ainsi que les classes de colonnes pour définir les largeurs sont ajoutées et nous n'avons pas besoin d'analyser le HTML pour extraire le contenu que nous mesurons.

Ensuite, nous devons choisir une stratégie pour sélectionner nos largeurs de colonne. Par exemple, la démo ci-dessous mesure les colonnes et trouve des pourcentages de largeur minimum pour chacun en fonction du mot le plus long. (Évite les sauts de mots) Distribue ensuite tout espace supplémentaire proportionnellement en fonction de la différence entre le mot le plus long et le contenu de cellule complet le plus long. Je ne dirais pas que cette production est prête car c'est une preuve de concept, mais j'espère que vous (ou d'autres chercheurs) la trouverez comme un point de départ utile.

La partie clé pour cela ci-dessous est la suivante: $tablebuilder->determine_column_widths_by_minimum_strategy('100%', 'aaa')

Le premier paramètre nous donne la référence de taille avec laquelle nous travaillons (100% de la page car j'en avais besoin pour rendre les mesures utiles), et le second fournit des caractères de remplissage prédéfinis à ajouter à nos mesures pour tenir compte du style de texte et du tableau différences de rembourrage.

Voici une démonstration de celui-ci en cours d'exécution: https://b65sol.com/so/59517311_new.php

La classe elle-même est disponible ici: https://github.com/b65sol/random-classes

Le code de cette démo est ici:

<?php
require 'vendor/autoload.php';
include 'random-classes/html2pdf-full-table-optimizer.php';
use Spipu\Html2Pdf\Html2Pdf;

//First let's build a random table!
$wordlist = ['Chocolate', 'Cake', 'Brownies', 'Cupcakes', 'Coreshock', 'Battery', 'Lead', 'Acid', 'Remilia'];
$wordlist2 = ['Reinforcement Learning', 'Initial Latent Vectors', 'Bag-of-Words', 'Multilayer Perceptron Classifier',
  'Deconvolutional Neural Network', 'Convolutional Neural Network'];
$number_of_columns = rand(3,11);
$number_of_rows = rand(8, 15);
$possible_column_names = ['Unit', 'Description', 'Variable', 'Moon', 'Cheese', 'Lollipop', 'Orange', 'Gir', 'Gaz', 'Zim', 'Dib'];
$possible_column_content_generators = [
  function() {return rand(10,100); },
  function() {return rand(1000, 1999); },
  function() use ($wordlist) {return $wordlist[rand(0, count($wordlist)-1)]; },
  function() use ($wordlist) {return $wordlist[rand(0, count($wordlist)-1)] . ' '. $wordlist[rand(0, count($wordlist)-1)];},
  function() use ($wordlist2) {return $wordlist2[rand(0, count($wordlist2)-1)];},
];

shuffle($possible_column_names);
$list_of_generators = [];
$column_classes = [];
$column_names = [];
for($i = 0; $i < $number_of_columns; $i++) {
  $list_of_generators[$i] = $possible_column_content_generators[rand(0, count($possible_column_content_generators)-1)];
  $column_classes[$i] = ['text-left', 'text-right', 'text-center'][rand(0,2)];
  $column_names[$i] = $possible_column_names[$i];
}
//Got our random stuff, onward to generator!

try {
    $html2pdf = new Html2Pdf('P', 'A4', 'en', true, 'UTF-8', 5);
    $html2pdf->pdf->SetDisplayMode('real');
    $tablebuilder = new Html2PdfTableOptimizer($html2pdf->pdf, '11px', 'helvetica');

    //run table builder... using random data for testing.
    for($i = 0; $i < $number_of_columns; $i++) {
      /*Add a header cell, content is the first parameter, CSS class attribute is second.*/
      $tablebuilder->add_header_cell($column_names[$i], $column_classes[$i] . ' bg-dark text-white');
    }

    for($i = 0; $i < $number_of_rows; $i++) {
      //Start a row.
      $tablebuilder->start_data_row();
      for($col = 0; $col < $number_of_columns; $col++) {
        //Add content and our column classes for td elements
        $tablebuilder->add_data_row_cell($list_of_generators[$col](), $column_classes[$col]);
      }
      //End the row.
      $tablebuilder->end_data_row();
    }
    //Get the table HTML.
    $render = $tablebuilder->render_html();

    $newContent = '
      <style type="text/css">
      table{width:100%;}
      table, table td, table th{
          border-collapse: collapse;
          border: solid 1px #ababab;
      }
      .text-dark, table td{
          color: #343a40;
      }
      .text-white{
          color: #ffffff;
      }
      table td,
      table th {
          font-size: 11px;
          padding: 3px;
          line-height: 1.2;
          font-family:arial;
      }

      .bg-dark {
          background-color: #343a40;
      }
      .bg-secondary {
          background-color: #6c757d;
      }
      .bg-white {
          background-color: #ffffff;
      }
      .row-even {
        background-color: #d1d1d1;
      }
      .text-left {
          text-align: left;
      }
      .text-right {
          text-align: right;
      }
      .text-center {
          text-align: center;
      }

      '.$tablebuilder->determine_column_widths_by_minimum_strategy('100%', 'aaa').'

      </style>
      ';
      $newContent .= '<page>'.$render.'</page>';

      if(!empty($_GET['html'])) {
        echo $newContent;
      } else {
        $html2pdf->writeHTML($newContent);
        $PDFName = "ItemLists_".date('Y.m.d_H.i.s').".pdf";
        $html2pdf->output($PDFName, 'I');
      }
} catch (Html2PdfException $x) {
    $html2pdf->clean();

    $formatter = new ExceptionFormatter($x);
    echo $formatter->getHtmlMessage();
}

FIN DE MISE À JOUR


Si vous préférez ne pas spécifier les largeurs de manière explicite, vous pouvez utiliser TCPDF au writeHTMLlieu d'utiliser la Html2PDFbibliothèque, mais tout ce qui va faire est d'utiliser des colonnes de taille égale. En fait, je pensais que cela ferait un recalcul des tailles de colonne si vous n'en spécifiiez qu'un ou deux, mais je me trompais. En outre, TCPDF souffre de certaines des mêmes limitations que Html2PDF- si vous spécifiez la taille d'une colonne, il ne redimensionnera pas automatiquement les autres colonnes pour s'adapter.

Il ne redimensionne pas non plus les colonnes au contenu comme le fait un navigateur. C'est en fait assez difficile à bien faire, donc je ne suis pas surpris que TCPDF ne l'essaye pas. Une solution potentiellement à faible effort serait de marquer vos colonnes avec une «proportion» de taille et de calculer les largeurs à la volée pour chacune en fonction du nombre de colonnes de taille proportionnelle sélectionnées. (par exemple, les colonnes numériques sont «petites», et une colonne de description serait «grande» et elle se divise donc en deux petites à 10% chacune et une seule description à 80%. Deux petites à 5% et de grandes colonnes à 45% Cela prendrait une certaine expérimentation.)

EPB
la source
merci pour votre temps, le problème est que j'utilise un tableau dynamique, il y a 10 colonnes qui peuvent être choisies par les utilisateurs, peut-être 5 cols ou 8 cols ou peut-être 2 cols qui est facultatif il y a une autre façon de le faire et c'est : table th, table td { <?=floor(100 / count($cols))?>%;}mais je cherche une meilleure solution
Mohsen Newtoa
1
À quel point Html2PDFêtes-vous engagé ? Toute ma lecture du code et des exemples suggère que c'est la seule façon. TCPDF peut le faire avec son analyse CSS légèrement moins performante, mais il a un meilleur système de mise en page. Je peux suggérer un balisage pour TCPDF direct.
EPB
J'ai essayé TCPDF et j'ai réalisé qu'ils utilisent la même méthode que j'utilise mais cela ne résout toujours pas mon problème, si je change une cellule, cela affectera les autres cellules et la largeur du tableau ne correspond toujours pas à la page, la différence entre TCPDF et HTML2PDF est que TCPDF utilise la taille de table par défaut comme la miennetable th, table td { <?=floor(100 / count($cols))?>%;}
Mohsen Newtoa
En effet, c'est aussi le problème que j'ai rencontré. Je pensais que cela me permettrait de spécifier la taille de certains uniquement et d'ajuster automatiquement le reste lorsque je configurais mon test (ce qui, bien qu'idéal, aurait l'air assez agréable avec peu d'effort), mais ce n'est pas ... du tout . Je vais creuser un peu plus et voir s'il existe un moyen à faible effort de dimensionner automatiquement les colonnes. Il faudrait que ce soit une sorte de prétraitement car ni l'un Html2PDFni l' autre ne TCPDFsemble le faire hors de la boîte.
EPB
Je ne sais pas si cela vous informe des mises à jour, mais j'ai ajouté une classe qui dimensionne dynamiquement les tableaux textuels en fonction de leur contenu. Il existe également une stratégie appelée determine_column_widths_evenlyqui vous permet de spécifier quelques tailles connues et de répartir uniformément l'espace restant.
EPB
0

Travailler avec le côté serveur de PDF n'est pas idéal pour CSS. Avez-vous essayé d'utiliser uniquement du HTML?

Par exemple:

<table width="100%">
  <!-- your table code -->
</table>

Vous pouvez également essayer:

<table style="width: 100%;">
  <!-- your table code -->
</table>

Voici un CodePen qui montre que cela fonctionne dans le navigateur. https://codepen.io/tinacious/pen/PowJRbb

Tina
la source
J'ai essayé tout cela: <table width="100%"> <table style="width:100%;"> <table class="w100"> <link rel="stylesheet" href="style.css" />mais le problème est que cela fonctionne très bien en html mais quand je veux l'enregistrer au format PDF, ce sera comme l'image.
Mohsen Newtoa
0

l'image: entrez la description de l'image ici

Je pense que la meilleure façon pour ce type de tableaux est d'utiliser cette façon:

table th, table td { width:<?=floor(100 / count($cols))?>%;}

sur TCPDF, ils n'ont rien fait de spécial, le tableau ne tient pas sur la page de toute façon.

Mohsen Newtoa
la source