FPDF 中 MultiCell 的换行问题

问题描述 投票:0回答:6

我正在使用 FPDF 的 Java 端口。我遇到以下错误。

  1. 当我调用 multicell 两次时,每次文本都会打印在新行上。
MultiCell(0, 1, "abcd", currentBorders, Alignment.LEFT, false); //prints on one line
MultiCell(0, 1, "efg", currentBorders, Alignment.LEFT, false); //prints on next line

我希望在调用多单元格后没有换行符。我该怎么办?

  1. 如果我执行以下操作,则字符串的某些部分将打印在一行上,而某些部分将打印在下一行上。
MultiCell(getStringWidth(myString), 1, myStringcurrentBorders, Alignment.LEFT, false);
  1. 如果我执行以下操作,则打印 myString 的行后面会有许多空行。如果我使用一个 1 作为第二个参数,它就可以正常工作。
MultiCell(0, myFontSize, "123456", currentBorders, Alignment.LEFT, false);

有什么问题吗?

php pdf-generation fpdf
6个回答
25
投票

我会在写入

Y
之前获取当前
MultiCell
位置,然后在
Y
生成之后将“光标”移回该
MultiCell
位置。像这样:

$current_y = $pdf->GetY();
$current_x = $pdf->GetX();

$cell_width = 50;
MultiCell($cell_width, 1, "abcd", currentBorders, Alignment.LEFT, false);

$pdf->SetXY($current_x + $cell_width, $current_y);

$current_x = $pdf->GetX();
MultiCell($cell_width, 1, "abcd", currentBorders, Alignment.LEFT, false);

类似这样的事情。


6
投票

我创建了一个名为

MultiAlignCell
的新方法。它采用与
MultiCell
相同的参数,但添加了
ln
 中的 
Cell
字段。您可以将其添加到您的扩展
FPDF
课程中。

/**
* MultiCell with alignment as in Cell.
* @param float $w
* @param float $h
* @param string $text
* @param mixed $border
* @param int $ln
* @param string $align
* @param boolean $fill
*/
private function MultiAlignCell($w,$h,$text,$border=0,$ln=0,$align='L',$fill=false)
{
    // Store reset values for (x,y) positions
    $x = $this->GetX() + $w;
    $y = $this->GetY();

    // Make a call to FPDF's MultiCell
    $this->MultiCell($w,$h,$text,$border,$align,$fill);

    // Reset the line position to the right, like in Cell
    if( $ln==0 )
    {
        $this->SetXY($x,$y);
    }
}

3
投票

我修改了MultiCell方法,它的工作原理与上面的答案相同,您可以像Cell方法一样使用该方法。

function MultiCell($w, $h, $txt, $border=0, $ln=0, $align='J', $fill=false)
{
    // Custom Tomaz Ahlin
    if($ln == 0) {
        $current_y = $this->GetY();
        $current_x = $this->GetX();
    }

    // Output text with automatic or explicit line breaks
    $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--;
    $b = 0;
    if($border)
    {
        if($border==1)
        {
            $border = 'LTRB';
            $b = 'LRT';
            $b2 = 'LR';
        }
        else
        {
            $b2 = '';
            if(strpos($border,'L')!==false)
                $b2 .= 'L';
            if(strpos($border,'R')!==false)
                $b2 .= 'R';
            $b = (strpos($border,'T')!==false) ? $b2.'T' : $b2;
        }
    }
    $sep = -1;
    $i = 0;
    $j = 0;
    $l = 0;
    $ns = 0;
    $nl = 1;
    while($i<$nb)
    {
        // Get next character
        $c = $s[$i];
        if($c=="\n")
        {
            // Explicit line break
            if($this->ws>0)
            {
                $this->ws = 0;
                $this->_out('0 Tw');
            }
            $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
            $i++;
            $sep = -1;
            $j = $i;
            $l = 0;
            $ns = 0;
            $nl++;
            if($border && $nl==2)
                $b = $b2;
            continue;
        }
        if($c==' ')
        {
            $sep = $i;
            $ls = $l;
            $ns++;
        }
        $l += $cw[$c];
        if($l>$wmax)
        {
            // Automatic line break
            if($sep==-1)
            {
                if($i==$j)
                    $i++;
                if($this->ws>0)
                {
                    $this->ws = 0;
                    $this->_out('0 Tw');
                }
                $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
            }
            else
            {
                if($align=='J')
                {
                    $this->ws = ($ns>1) ?     ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0;
                    $this->_out(sprintf('%.3F Tw',$this->ws*$this->k));
                }
                $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill);
                $i = $sep+1;
            }
            $sep = -1;
            $j = $i;
            $l = 0;
            $ns = 0;
            $nl++;
            if($border && $nl==2)
                $b = $b2;
        }
        else
            $i++;
    }
    // Last chunk
    if($this->ws>0)
    {
        $this->ws = 0;
        $this->_out('0 Tw');
    }
    if($border && strpos($border,'B')!==false)
        $b .= 'B';
    $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
    $this->x = $this->lMargin;

    // Custom Tomaz Ahlin
    if($ln == 0) {
        $this->SetXY($current_x + $w, $current_y);
    }
}

0
投票

在我的例子中,我没有创建任何方法,我只是设置了 X 和 Y,然后在行的末尾我重置了。它也完美运行。

        $pdf->SetFont('times', 'B', 10);
        $x = $pdf->GetX();
        $y = $pdf->GetY();
        $pdf->MultiCell($etiquetas_largura, $etiquetas_altura, $campos[$linha]['B1COD'], 0, 'L', 0, 0, $x, $y, true, 0, false, true, 0);
        $y = $y + 5;
        $pdf->SetFont('times', '', 10);
        $pdf->MultiCell($etiquetas_largura, $etiquetas_altura, $campos[$linha]['B1DESC'], 0, 'L', 0, 0, $x, $y, true, 0, false, true, 0);
        // resete x y
        $pdf->SetXY($x + $etiquetas_largura, $y - 5);

0
投票

@Muhammad Abdul Rahim 和@tomazahlin 提供了很好的方法。他们只解决了单个单元格中的换行问题。它们的主题单元格的高度与同一行中的其他单元格的高度不匹配。如果处理动态表,使用 GetY() 会变得很复杂。我发现的最简单的解决方案是识别可能有溢出文本的列并将其用作参考。

$l=strlen($string_of_reference_cell);
$h = ceil($l/$cell_width*1.5)*preferred_normal_height;//1.5 is a loading for allowance`depending on font size.

$pdf->cell(20,$h,$string,1,0);
$pdf->MultiAlignCell(50,5,$string_of_reference_cell,1,0);// 5 is the preferred normal height
$pdf->Cell(23,$h,$string,1,1);

生成pdf时,如果MultiAlignCell的字符串长于单元格宽度,则会产生换行。所得高度是两倍 (5 x 2 = 10)。 10 的高度被指定为 $h。因此,其他单元格也采用 $h 的高度,并且整行获得统一的高度。


0
投票

我也在努力解决多单元问题,但这是缩放文本并使其适合的更好的解决方案。

所以我扩展了该类并调用了

CellFitScale
函数。

<?php
namespace App\Pdf;
use Fpdf\Fpdf;

//require('fpdf.php');
class FPDF_CellFit extends Fpdf
{
  //Cell with horizontal scaling if text is too wide
  function CellFit($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='', $scale=false, $force=true)
  {
    //Get string width
    $str_width=$this->GetStringWidth($txt);

    //Calculate ratio to fit cell
    if($w==0)
      $w = $this->w-$this->rMargin-$this->x;
    $ratio = ($w-$this->cMargin*2)/$str_width;

    $fit = ($ratio < 1 || ($ratio > 1 && $force));
    if ($fit)
    {
      if ($scale)
      {
        //Calculate horizontal scaling
        $horiz_scale=$ratio*100.0;
        //Set horizontal scaling
        $this->_out(sprintf('BT %.2F Tz ET',$horiz_scale));
      }
      else
      {
        //Calculate character spacing in points
        $char_space=($w-$this->cMargin*2-$str_width)/max(strlen($txt)-1,1)*$this->k;
        //Set character spacing
        $this->_out(sprintf('BT %.2F Tc ET',$char_space));
      }
      //Override user alignment (since text will fill up cell)
      $align='';
    }

    //Pass on to Cell method
    $this->Cell($w,$h,$txt,$border,$ln,$align,$fill,$link);

    //Reset character spacing/horizontal scaling
    if ($fit)
      $this->_out('BT '.($scale ? '100 Tz' : '0 Tc').' ET');
  }

  //Cell with horizontal scaling only if necessary
  function CellFitScale($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='')
  {
    $this->CellFit($w,$h,$txt,$border,$ln,$align,$fill,$link,true,false);
  }

  //Cell with horizontal scaling always
  function CellFitScaleForce($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='')
  {
    $this->CellFit($w,$h,$txt,$border,$ln,$align,$fill,$link,true,true);
  }

  //Cell with character spacing only if necessary
  function CellFitSpace($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='')
  {
    $this->CellFit($w,$h,$txt,$border,$ln,$align,$fill,$link,false,false);
  }

  //Cell with character spacing always
  function CellFitSpaceForce($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='')
  {
    //Same as calling CellFit directly
    $this->CellFit($w,$h,$txt,$border,$ln,$align,$fill,$link,false,true);
  }
}

然后在我的 PDF 生成中,我像这样使用它:

$fpdf->CellFitScale(45, 8, trim('一些很长的文本!'), 1, 0, 'L');

我希望它有帮助。干杯!

© www.soinside.com 2019 - 2024. All rights reserved.