Tabela de página inteira do TCPDF

11

Tentei várias maneiras de ajustar a tabela à página (A4), como mostra a figura: insira a descrição da imagem aqui pesquisei bastante, mas não encontrei nada útil na web. Estou usando tabela dinâmica, está tudo bem, exceto a largura da tabela. aqui está o meu 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();
    }

Muito Obrigado

Mohsen Newtoa
fonte
Este é realmente um bug na biblioteca Html2PDF. Olhando para uma possível solução alternativa.
EPB
Vale a pena notar, aliás, que o Html2PDF usa seu próprio analisador de HTML. style="width: 100%"armazena a largura convertida corretamente em MM (embora o atributo width não o faça!) No entanto, o Html2PDF não parece realmente usá-lo durante a renderização da tabela.
EPB

Respostas:

4

O Html2PDF não usa o sistema analisador / renderizador de HTML do TCPDF. Ele implementa por si próprio e sua implementação não aumentará as colunas automaticamente para preencher 100% do espaço.

Dessa forma, no Html2PDF, você não apenas precisa definir 100% de largura na tabela, mas também definir larguras de porcentagem para cada uma das células. (E devido a algum comportamento estranho com o widthatributo em Html2PDF, use CSS para definir as larguras.)

O nativo do TCPDF writeHTMLdefinirá cada coluna com a mesma largura, sem nenhuma especificação. (Por exemplo, uma tabela de 4 colunas tem todas as células em 25%) No entanto, ela não suporta o CSS que você está usando, portanto a marcação exigiria alguns ajustes para seguir esse caminho.

Para imitar esse comportamento básico no Html2PDF, você pode simplesmente adicionar larguras equivalentes às suas células explicitamente. Por exemplo, adicionando uma especificação de largura às suas table td, table thregras de estilo.

Aqui está um exemplo com as seguintes regras CSS para uma tabela de quatro colunas:

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

Obviamente, fica melhor quando você especifica larguras que se encaixam no seu conteúdo.

Exemplo com colunas equivalentes


ATUALIZAR

Vou deixar parte da discussão sobre o TCPDF abaixo, pois isso leva à criação de uma classe potencialmente útil para Html2pdf. O TCPDF possui alguns métodos úteis para medir o comprimento de uma string. Se você medir o tamanho das cadeias dentro das colunas, poderá criar seu próprio dimensionador automático de colunas.

Criei uma classe de prova de conceito no github em https://github.com/b65sol/random-classes

Primeiro, usamos a classe para mediar a construção do HTML. Assim, as classes de coluna para definir as larguras são adicionadas e não precisamos analisar o HTML para extrair o conteúdo que estamos medindo.

Então temos que escolher uma estratégia para selecionar as larguras das nossas colunas. Por exemplo, a demonstração abaixo mede as colunas e localiza as porcentagens mínimas de largura para cada uma, com base na palavra mais longa. (Evita quebras de palavras) Em seguida, distribui qualquer espaço extra proporcionalmente com base na diferença entre a palavra mais longa e o conteúdo mais completo da célula. Eu não chamaria essa produção de pronta, pois é uma prova de conceito, mas espero que você (ou outros pesquisadores) a considerem um ponto de partida útil.

A parte principal para isso abaixo é esta: $tablebuilder->determine_column_widths_by_minimum_strategy('100%', 'aaa')

O primeiro parâmetro nos fornece a referência de tamanho com a qual estamos trabalhando (100% da página, conforme necessário para tornar as medidas úteis), e o segundo fornece alguns caracteres de preenchimento predefinidos para adicionar às nossas medições, levando em consideração o estilo do texto e a tabela diferenças de preenchimento.

Aqui está uma demonstração dele em execução: https://b65sol.com/so/59517311_new.php

A classe em si está disponível aqui: https://github.com/b65sol/random-classes

O código para essa demonstração está aqui:

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

FIM DA ATUALIZAÇÃO


Se você preferir não especificar as larguras explicitamente, poderá usar os TCPDFs em writeHTMLvez de usar a Html2PDFbiblioteca, mas tudo o que fará será usar colunas de tamanho igual. Na verdade, eu pensei que faria algum recálculo do tamanho da coluna se você especificasse apenas um ou dois, mas eu estava incorreto. Além disso, o TCPDF sofre algumas das mesmas limitações de Html2PDF- se você especificar o tamanho de uma coluna, ele não redimensionará automaticamente as outras colunas para ajustá-las.

Ele também não dimensiona colunas para o conteúdo da mesma forma que um navegador. Isso é realmente muito difícil de fazer, então não estou surpreso que o TCPDF não tente. Uma solução potencialmente de baixo esforço seria marcar suas colunas com um tamanho 'proporção' e calcular as larguras em tempo real para cada um, dependendo de quantas colunas de cada tamanho proporcional estão selecionadas. (por exemplo, colunas numéricas são 'pequenas' e uma coluna de descrição seria 'grande' e, portanto, divide duas pequenas em 10% cada e uma única descrição em 80%. Duas pequenas em 5% e em grandes colunas em 45% cada um. Seria necessário experimentação.)

EPB
fonte
obrigado pelo seu tempo, o problema é que estou usando tabela dinâmica, existem 10 colunas que podem ser escolhidas pelos usuários, talvez 5 ou 8 colunas ou talvez 2 colunas que são opcionais. Existe outra maneira de fazer isso e é : table th, table td { <?=floor(100 / count($cols))?>%;}mas estou procurando uma solução melhor
Mohsen Newtoa
11
Como Html2PDFvocê está comprometido ? Toda a minha leitura do código e exemplos sugere que este é o único caminho. O TCPDF pode fazer isso com sua análise CSS um pouco menos capaz, mas possui um sistema de layout melhor. Eu posso sugerir marcação para TCPDF direto.
EPB
Tentei o TCPDF e percebi que eles usam o mesmo método que eu, mas ainda assim não resolve o problema. Se eu alterar uma célula, ela afetará as outras células e a largura da tabela ainda não se ajustará à página, a diferença entre TCPDF e HTML2PDF é que o TCPDF está usando o tamanho da tabela padrão como o meutable th, table td { <?=floor(100 / count($cols))?>%;}
Mohsen Newtoa
Na verdade, esse também foi o problema que tive. Eu pensei que me permitiria especificar o tamanho de apenas alguns específicos e ajustar automaticamente o resto quando eu configurar o meu teste (que, embora não seja o ideal, pareceria razoavelmente agradável com pouco esforço), mas não ... . Vou fazer um pouco mais de escavação e ver se há alguma maneira de baixo esforço para dimensionar automaticamente as colunas. Teria que ser algum tipo de pré-processamento, embora nenhum Html2PDFou TCPDFpareça fazê-lo fora da caixa.
EPB
Não tenho certeza se ele notifica as atualizações, mas adicionei uma classe que dimensiona dinamicamente as tabelas baseadas em texto com base em seu conteúdo. Há também uma estratégia chamada determine_column_widths_evenlyque permite especificar alguns tamanhos conhecidos e distribuir uniformemente o espaço restante.
EPB
0

Trabalhar com o lado do servidor do PDF não é bom para CSS. Você já tentou usar apenas HTML?

Por exemplo:

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

Como alternativa, você pode tentar:

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

Aqui está um CodePen que demonstra isso funcionando no navegador. https://codepen.io/tinacious/pen/PowJRbb

Tina
fonte
Eu tentei tudo isso: <table width="100%"> <table style="width:100%;"> <table class="w100"> <link rel="stylesheet" href="style.css" />mas a questão é que, ele funciona bem em html, mas quando eu quero salvá-lo como PDF, será como a imagem.
Mohsen Newtoa 01/01
0

a imagem: insira a descrição da imagem aqui

Eu acho que a melhor maneira para este tipo de tabelas é usando desta maneira:

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

no TCPDF, eles não fizeram nada de especial; a tabela não se encaixa na página.

Mohsen Newtoa
fonte