FPDF WriteHTML()多表呈现只显示第一个正确

时间:2016-04-15 13:11:40

标签: php pdf-generation fpdf

我正在使用FPDF来呈现html内容中的表格。 因此,当我想渲染表格时,我得到了这个link来渲染表格。问题是我在html中一个接一个地有两个表,我不能将它分开,因为内容来自 <?php //Based on HTML2PDF by Clément Lavoillotte require('fpdf/fpdf.php'); require('htmlparser.inc.php'); class PDF_HTML_Table extends FPDF { var $B; var $I; var $U; var $HREF; function PDF($orientation='P', $unit='mm', $format='A4') { //Call parent constructor $this->FPDF($orientation,$unit,$format); //Initialization $this->B=0; $this->I=0; $this->U=0; $this->HREF=''; } function WriteHTML2($html) { //HTML parser $html=str_replace("\n",' ',$html); $a=preg_split('/<(.*)>/U',$html,-1,PREG_SPLIT_DELIM_CAPTURE); foreach($a as $i=>$e) { if($i%2==0) { //Text if($this->HREF) $this->PutLink($this->HREF,$e); else $this->Write(5,$e); } else { //Tag if($e[0]=='/') $this->CloseTag(strtoupper(substr($e,1))); else { //Extract attributes $a2=explode(' ',$e); $tag=strtoupper(array_shift($a2)); $attr=array(); foreach($a2 as $v) { if(preg_match('/([^=]*)=["\']?([^"\']*)/',$v,$a3)) $attr[strtoupper($a3[1])]=$a3[2]; } $this->OpenTag($tag,$attr); } } } } function OpenTag($tag, $attr) { //Opening tag if($tag=='B' || $tag=='I' || $tag=='U') $this->SetStyle($tag,true); if($tag=='A') $this->HREF=$attr['HREF']; if($tag=='BR') $this->Ln(5); if($tag=='P') $this->Ln(10); } function CloseTag($tag) { //Closing tag if($tag=='B' || $tag=='I' || $tag=='U') $this->SetStyle($tag,false); if($tag=='A') $this->HREF=''; if($tag=='P') $this->Ln(10); } function SetStyle($tag, $enable) { //Modify style and select corresponding font $this->$tag+=($enable ? 1 : -1); $style=''; foreach(array('B','I','U') as $s) if($this->$s>0) $style.=$s; $this->SetFont('',$style); } function PutLink($URL, $txt) { //Put a hyperlink $this->SetTextColor(0,0,255); $this->SetStyle('U',true); $this->Write(5,$txt,$URL); $this->SetStyle('U',false); $this->SetTextColor(0); } function WriteTable($data, $w) { $this->SetLineWidth(.3); $this->SetFillColor(255,255,255); $this->SetTextColor(0); $this->SetFont(''); foreach($data as $row) { $nb=0; for($i=0;$i<count($row);$i++) $nb=max($nb,$this->NbLines($w[$i],trim($row[$i]))); $h=5*$nb; $this->CheckPageBreak($h); for($i=0;$i<count($row);$i++) { $x=$this->GetX(); $y=$this->GetY(); $this->Rect($x,$y,$w[$i],$h); $this->MultiCell($w[$i],5,trim($row[$i]),0,'C'); //Put the position to the right of the cell $this->SetXY($x+$w[$i],$y); } $this->Ln($h); } } function NbLines($w, $txt) { //Computes the number of lines a MultiCell of width w will take $cw=&$this->CurrentFont['cw']; if($w==0) $w=$this->w-$this->rMargin-$this->x; $wmax=($w-2*$this->cMargin)*1000/$this->FontSize; $s=str_replace("\r",'',$txt); $nb=strlen($s); if($nb>0 && $s[$nb-1]=="\n") $nb--; $sep=-1; $i=0; $j=0; $l=0; $nl=1; while($i<$nb) { $c=$s[$i]; if($c=="\n") { $i++; $sep=-1; $j=$i; $l=0; $nl++; continue; } if($c==' ') $sep=$i; $l+=$cw[$c]; if($l>$wmax) { if($sep==-1) { if($i==$j) $i++; } else $i=$sep+1; $sep=-1; $j=$i; $l=0; $nl++; } else $i++; } return $nl; } function CheckPageBreak($h) { //If the height h would cause an overflow, add a new page immediately if($this->GetY()+$h>$this->PageBreakTrigger) $this->AddPage($this->CurOrientation); } function ReplaceHTML($html) { $html = str_replace( '<li>', "\n<br> - " , $html ); $html = str_replace( '<LI>', "\n - " , $html ); $html = str_replace( '</ul>', "\n\n" , $html ); $html = str_replace( '<strong>', "<b>" , $html ); $html = str_replace( '</strong>', "</b>" , $html ); $html = str_replace( '&#160;', "\n" , $html ); $html = str_replace( '&nbsp;', " " , $html ); $html = str_replace( '&quot;', "\"" , $html ); $html = str_replace( '&#39;', "'" , $html ); return $html; } function ParseTable($Table) { $_var=''; $htmlText = $Table; $parser = new HtmlParser ($htmlText); while ($parser->parse()) { if(strtolower($parser->iNodeName)=='table') { if($parser->iNodeType == NODE_TYPE_ENDELEMENT) $_var .='/::'; else $_var .='::'; } if(strtolower($parser->iNodeName)=='tr') { if($parser->iNodeType == NODE_TYPE_ENDELEMENT) $_var .='!-:'; //opening row else $_var .=':-!'; //closing row } if(strtolower($parser->iNodeName)=='td' && $parser->iNodeType == NODE_TYPE_ENDELEMENT) { $_var .='#,#'; } if ($parser->iNodeName=='Text' && isset($parser->iNodeValue)) { $_var .= $parser->iNodeValue; } } $elems = explode(':-!',str_replace('/','',str_replace('::','',str_replace('!-:','',$_var)))); //opening row foreach($elems as $key=>$value) { if(trim($value)!='') { $elems2 = explode('#,#',$value); array_pop($elems2); $data[] = $elems2; } } return $data; } function WriteHTML($html) { $html = $this->ReplaceHTML($html); //Search for a table $start = strpos(strtolower($html),'<table'); $end = strpos(strtolower($html),'</table'); if($start!==false && $end!==false) { $this->WriteHTML2(substr($html,0,$start).'<BR>'); $tableVar = substr($html,$start,$end-$start); $tableData = $this->ParseTable($tableVar); for($i=1;$i<=count($tableData[0]);$i++) { if($this->CurOrientation=='L') $w[] = abs(120/(count($tableData[0])-1))+24; else $w[] = abs(120/(count($tableData[0])-1))+5; } $this->WriteTable($tableData,$w); $this->WriteHTML2(substr($html,$end+8,strlen($html)-1).'<BR>'); } else { $this->WriteHTML2($html); } } } 编辑器。这里的第一张表工作正常。但对于第二张表,它根本不起作用。我检查了所有标记,一切看起来都不错。

html_table.php就像这样

<?php
require('html_table.php');

$pdf = new PDF_HTML_Table();
$pdf->AddPage();
$pdf->SetFont('Arial','',12);

$html='<table border="1">
<tr>
<td width="200" height="30">cell 1</td><td width="200" height="30" bgcolor="#D0D0FF">cell 2</td>
</tr>
<tr>
<td width="200" height="30">cell 3</td><td width="200" height="30">cell 4</td>
</tr>
</table>
<br>
<br>
<table border="1">
<tr>
<td width="200" height="30">cell 5</td><td width="200" height="30" bgcolor="#D0D0FF">cell 6</td>
</tr>
<tr>
<td width="200" height="30">cell 7</td><td width="200" height="30">cell 8</td>
</tr>
</table>
';

$pdf->WriteHTML($html);
$pdf->Output();
?>

并且index.php就像这样

public function getStartOfQuarter()
{
     return date(sprintf('Y-%s-01', floor((date('n') - 1) / 3) * 3 + 1));
}

public function getEndOfQuarter()
{
    return date(sprintf('Y-%s-t', floor((date('n') + 2) / 3) * 3));
}

有人能告诉我如何解决这个问题吗?任何帮助和建议都会非常明显。感谢

2 个答案:

答案 0 :(得分:1)

如果您使用HTML代码为使用FPDF库生成的PDF文档构建表,那么请查看FPDF easyTable项目https://github.com/fpdf-easytable/fpdf-easytable

$table=new easyTable($pdf, 3, 'border:1;');

// first row
$table->easyCell('Text 1', 'valign:T'); 
$table->easyCell('Text 2', 'bgcolor:#b3ccff;');
$table->easyCell('Text 3');
$table->printRow();

//second row
$table->rowStyle('min-height:20; align:{C}'); 
$table->easyCell('Text 4', 'colspan:3');
$table->printRow();

$table->endTable(4);

答案 1 :(得分:0)

前几天我遇到了这个问题,并提出了以下解决方案:

  1. 在FPDF类中,添加一个函数findAll()。这将用于查找HTML中的<table</table的所有实例以进行转换:

    function findAll($needle, $haystack) 
    {
      // initialize the return value array
      $rv = array();
    
      // set up a temp variable to make things simple
      $temp = 0;
    
      // successively find each instance of needle in haystack
      while($temp < strlen($haystack)) 
      {
        $temp = strpos($haystack,$needle, $temp);
    
        if($temp !== false) 
        {
          $rv[] = $temp;
          $temp++;
        } 
        else
        {
          // nothing to find
          return $rv;
        }
      }
    
      return $rv;
    }  
    
  2. WriteHTML()函数修改为a)使用findAll()查找所有表实例,b)替换每个实例(保持任何非表格格式不变)。此修改基本上将您的HTML“块”分为“表格”和“非表格”,并相应地格式化HTML:

      function WriteHTML($html)
      {
        $w = array();
    
        // search for a table
        $starts = $this->findAll('<table',strtolower($html));
        $ends = $this->findAll('</table',strtolower($html));
    
        if(count($starts) > 0 && count($ends) > 0)
        {
          $positions[0] = 'doc-start';
    
          foreach($starts as $key => $start)
          {
            $end = $ends[$key];
            $positions[$start] = 'table-start';
            $positions[$end] = 'table-end';
          }
    
          $endPos = strlen($html)-1;
          $positions[$endPos] = 'doc-end';
    
          $lastKnownPos = 0;
    
          for($q=1;$q<=$endPos;$q++)
          {
            if(isset($positions[$q]))
            {
              $curPos = $positions[$q];
    
              if($curPos == 'table-start')
              {
                $this->WriteHTML2(substr($html,$lastKnownPos,$q-$lastKnownPos).'<BR>'); 
                $lastKnownPos = $q;
              }
              else if($curPos == 'table-end')
              {
                $tableVar = substr($html,$lastKnownPos,$q-$lastKnownPos+8);
                $tableData = $this->ParseTable($tableVar);
    
                for($i=0;$i<count($tableData[0]);$i++)
                {
                  if($this->CurOrientation=='L')
                  {
                    $w[$i] = abs(277/(count($tableData[0])));
                  }
                  else
                  {
                    $w[$i] = abs(190/(count($tableData[0])));
                  }
                }
                $this->WriteTable($tableData,$w);
                $lastKnownPos = $q+8;
              }
              else if($curPos == 'doc-end')
              {
                $this->WriteHTML2(substr($html,$lastKnownPos,$q-$lastKnownPos).'<BR>'); 
                $lastKnownPos = $q;              
              }
            }
          }
        } 
        else
        {
          // if there is no table, just write the HTML as normal
          $this->WriteHTML2($html);
        }
      }