TCPDF tabla de página completa

11

Intenté muchas formas de hacer que la tabla se ajustara a la página (A4) como se muestra en la imagen: ingrese la descripción de la imagen aquí busqué mucho pero no pude encontrar nada útil en la web. Estoy usando una tabla dinámica, todo está bien, excepto el ancho de la tabla. Aquí está mi código:

$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();
    }

muchas gracias

Mohsen Newtoa
fuente
Esto es realmente un error en la biblioteca Html2PDF. Buscando una posible solución alternativa.
EPB
Vale la pena señalar, por cierto, que Html2PDF usa su propio analizador HTML. style="width: 100%"almacena el ancho convertido correctamente en MM (¡aunque el atributo de ancho no lo hace!) Sin embargo, Html2PDF no parece usarlo realmente durante la representación de la tabla.
EPB

Respuestas:

4

Html2PDF no utiliza el sistema de análisis / renderización HTML de TCPDF. Implementa su propio, y su implementación no hará crecer las columnas automáticamente para llenar el 100% del espacio.

Como tal, en Html2PDF, no solo necesita establecer un ancho del 100% en la tabla, sino que también necesita establecer porcentajes de ancho para cada una de las celdas. (Y debido a un comportamiento extraño con el widthatributo en Html2PDF, use CSS para establecer los anchos).

El nativo de TCPDF writeHTMLconfigurará cada columna para que tenga el mismo ancho en ausencia de cualquier otra especificación. (Por ejemplo, una tabla de 4 columnas tiene todas las celdas al 25%) Sin embargo, no admite el CSS que está utilizando, por lo que el marcado requeriría un pequeño ajuste para seguir esa ruta.

Para imitar este comportamiento básico en Html2PDF, simplemente puede agregar anchos equivalentes a sus celdas explícitamente. Por ejemplo, agregar una especificación de ancho a sus table td, table threglas de estilo.

Aquí hay un ejemplo con las siguientes reglas CSS para una tabla de cuatro columnas:

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

Por supuesto, se ve mejor cuando especifica anchos que se ajustan a su contenido.

Ejemplo con columnas equivalentes


ACTUALIZAR

Voy a dejar parte de la discusión sobre TCPDF a continuación, ya que conduce a la creación de una clase potencialmente útil para Html2pdf. TCPDF tiene algunos métodos útiles para medir la longitud de una cadena. Si mide el tamaño de las cadenas dentro de las columnas, puede crear su propio dimensionador automático de columnas.

Creé una clase de prueba de concepto en github en https://github.com/b65sol/random-classes

Primero, usamos la clase para mediar en la construcción del HTML. Esto es para que se agreguen las clases de columnas para establecer los anchos y no tengamos que analizar HTML para extraer el contenido que estamos midiendo.

Luego tenemos que elegir alguna estrategia para seleccionar nuestros anchos de columna. Por ejemplo, la demostración a continuación mide las columnas y encuentra porcentajes de ancho mínimo para cada uno según la palabra más larga. (Evita los saltos de palabras) Luego distribuye cualquier espacio adicional proporcionalmente en función de la diferencia entre la palabra más larga y el contenido de celda completa más largo. No llamaría a esta producción lista ya que es una prueba de concepto, pero espero que usted (u otros buscadores) la encuentre como un punto de partida útil.

La parte clave para eso a continuación es esta: $tablebuilder->determine_column_widths_by_minimum_strategy('100%', 'aaa')

El primer parámetro nos da la referencia de tamaño con la que estamos trabajando (100% de la página, ya que necesitaba esto para que las medidas sean útiles), y el segundo proporciona algunos caracteres de relleno preestablecidos para agregar a nuestras medidas para tener en cuenta el estilo de texto y la tabla Diferencias de relleno.

Aquí hay una demostración en ejecución: https://b65sol.com/so/59517311_new.php

La clase en sí está disponible aquí: https://github.com/b65sol/random-classes

El código para esa demostración está aquí:

<?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 ACTUALIZACIÓN


Si prefiere no especificar los anchos explícitamente, puede usar TCPDF en writeHTMLlugar de usar la Html2PDFbiblioteca, pero todo lo que hará es usar columnas de igual tamaño. De hecho, pensé que haría un nuevo cálculo de los tamaños de columna si solo especificabas uno o dos, pero era incorrecto. Además, TCPDF tiene algunas de las mismas limitaciones que Html2PDF: si especifica el tamaño de una columna, no cambiará automáticamente el tamaño de las otras columnas para que quepan.

Tampoco ajusta el tamaño de las columnas al contenido como lo hace un navegador. En realidad, esto es bastante difícil de hacer, así que no me sorprende que TCPDF no lo intente. Una solución de bajo esfuerzo potencial sería etiquetar sus columnas con una 'proporción' de tamaño y calcular los anchos sobre la marcha para cada uno dependiendo de cuántas columnas de tamaño proporcional se seleccionen. (por ejemplo, las columnas numéricas son 'pequeñas', y una columna de descripción sería 'grande' y, por lo tanto, divide dos pequeñas al 10% cada una y una única descripción al 80%. Dos pequeñas al 5% y columnas grandes al 45% cada uno. Haría falta algo de experimentación.)

EPB
fuente
gracias por su tiempo, el problema es que estoy usando una tabla dinámica, hay 10 columnas que pueden elegir los usuarios, tal vez 5 cols u 8 cols o tal vez 2 cols que es opcional, hay otra forma en que puedo hacerlo y es : table th, table td { <?=floor(100 / count($cols))?>%;}pero estoy buscando una solución mejor
Mohsen Newtoa
1
¿Qué tan comprometido Html2PDFestás? Toda mi lectura del código y ejemplos sugiere que esta es la única manera. TCPDF puede hacer esto con su análisis CSS un poco menos capaz, pero tiene un mejor sistema de diseño. Puedo sugerir un marcado para TCPDF directo.
EPB
Intenté TCPDF y me di cuenta de que usan el mismo método que yo, pero aún así no resuelve mi problema, si cambio una celda afectará a las otras celdas y el ancho de la tabla todavía no se ajusta a la página, La diferencia entre TCPDF y HTML2PDF es que TCPDF está utilizando el tamaño de tabla predeterminado como el míotable th, table td { <?=floor(100 / count($cols))?>%;}
Mohsen Newtoa
De hecho, ese es el problema con el que me encontré también. Yo pensé que me permitiría especificar el tamaño de los que se acaban específicos y auto-ajusta el resto cuando configuro mi prueba (que si bien no es lo ideal sería razonablemente agradable con poco esfuerzo), pero no lo hace en absoluto ... . Cavaré un poco más y veré si hay alguna forma de bajo esfuerzo para dimensionar automáticamente las columnas. Tendría que ser una especie de pre-procesamiento, aunque como no Html2PDFo TCPDFparecen hacerlo fuera de la caja.
EPB
No estoy seguro si le notifica las actualizaciones, pero agregué una clase que clasifica dinámicamente las tablas basadas en texto en función de su contenido. También hay una estrategia llamada determine_column_widths_evenlyque le permite especificar algunos tamaños conocidos y hacer que distribuya uniformemente el espacio restante.
EPB
0

Trabajar con el lado del servidor de PDF no es excelente para CSS. ¿Has intentado usar solo HTML?

Por ejemplo:

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

Alternativamente, puedes probar:

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

Aquí hay un CodePen que demuestra que esto funciona en el navegador. https://codepen.io/tinacious/pen/PowJRbb

Tina
fuente
Intenté todo esto: <table width="100%"> <table style="width:100%;"> <table class="w100"> <link rel="stylesheet" href="style.css" />pero el problema es que funciona bien en html, pero cuando quiera guardarlo como PDF, será como la imagen.
Mohsen Newtoa
0

la imagen: ingrese la descripción de la imagen aquí

Creo que la mejor manera para este tipo de tablas es usarlo de esta manera:

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

en TCPDF no han hecho nada especial, la tabla no cabe en la página de todos modos.

Mohsen Newtoa
fuente