9

我使用 FPDF 库将一些文档文件导出为 PDF。一个文档包括具有不同长度的字符串列表。我将所有字符串打印为$pdf->MultiCell(). 现在我想让 MultiCell 的当前高度具有相同的行距,以防它们只有一行或多行。

代码示例:

//MySQL Query
while($row = mysql_fetch_array($res) {
   $pdf->SetXY(18, $x);
   $pdf->MultiCell(80, 5, $rowr['text']); //text has one or more lines
   $x = $x + 10; // Here I would prefer a solution to say: $x = $x + 2 + height of the MultiCell()
}
4

4 回答 4

22

我有同样的问题; 我使用 FPDF 生成发票,每行有四个单元格,第一个单元格是具有不同高度的 MultiCell(默认高度为 5,但如果订单名称太长,它会在总高度 10 中添加另一行,依此类推) . 问题是剩下的 3 个单元格的高度是固定的。

在寻找解决方案之后,似乎唯一的方法是编写一个复杂的函数或使用一些第三方工具。由于我希望我的应用程序尽可能轻巧,因此我使用以下方法来解决它,我认为这比外部插件要简单得多。

  1. 发票详细信息的行从 Y=95 开始,所以我$Y=95; 在我的 while 循环之前使用
  2. 我的第一个单元格(MultiCell)如下:

    $pdf->SetXY(10,$Y);
    $pdf->MultiCell(60,5,$row['Name'],1,1,'L');
    
  3. 我使用 FPDF 的 GetY() 函数来获取当前高度并将其保存为 H:

    $H = $pdf->GetY();
    

    如果 MultiCell 的高度为 5,GetY() 将返回 100,如果高度为 10,GetY() 将返回 105,依此类推。

  4. 我添加了新变量 $height:

    $height= $H-$Y;
    

    结果就是给了我MultiCell的高度。

  5. 我使用 $Y 和 $height 来设置当前位置和列高:

    $pdf->SetXY(130,$Y);
    $pdf->Cell(40,$height,$row['RowName'],1,1,'L');
    
  6. 在完成 while 循环集之前,给 $Y $H 的值:

    $Y=$H;
    

整个循环如下所示并且完美运行:

$Y= 95;

$query = mysqli_query($con,"SELECT * FROM table");

while($row = mysqli_fetch_array($query)) {
    $pdf->SetXY(10,$Y);
    $pdf->MultiCell(60,5,$row['ROW1'],1,1,'L');

    $H = $pdf->GetY();
    $height= $H-$Y;

    $pdf->SetXY(70,$Y);
    $pdf->Cell(60,$height,$row['ROW2'],1,1,'L');
    $pdf->SetXY(130,$Y);
    $pdf->Cell(40,$height,$row['ROW3'],1,1,'L');
    $pdf->SetXY(170,$Y);
    $pdf->Cell(30,$height,$row['ROW4'],1,1,'L');

    $Y=$H;
}

如果每行中有 2 个或更多 MultiCell 列,它会变得很棘手,但仍然可以以类似的方式解决。

于 2015-04-15T01:52:27.827 回答
2

我正在用 golang 编码,所以我会展示一些伪代码。我希望可访问的方法phpgolang.

有一种方法叫做pdf.SplitLines(text, width)。您将传递您的字符串内容和所需的宽度,它将返回一个字符串数组,该数组表示将被计算以显示该内容的行。

有了它很容易。在伪代码中,它可能看起来像:

fontSize = 10;
lineHeight = 12;
targetWidth = 50;
pdf.SetFontSize(fontSize)
nLines = length(pdf.SplitLines(content, targetWidth));

multiCellHeight = nLines * lineHeight;
pdf.Multicell(targetWidth, lineHeight, content, ...) 

渲染MultiCell的大小与存储在multiCellHeight. 这样,您将在渲染之前获得高度。

这是有效的,因为传递heightMultiCelllineHeight每一行的。如果您在渲染之前知道行,您将获得总高度。


如果由于任何原因失败,我很抱歉php。让我知道是否是这种情况。

于 2019-03-11T11:23:43.003 回答
2

我在这里找到了有趣的解决方案 - https://github.com/artkonekt/pdf-invoice/blob/master/src/InvoicePrinter.php#L469

$calculateHeight = new self;
$calculateHeight->addPage();
$calculateHeight->setXY(0, 0);
$calculateHeight->SetFont($this->font, '', 7);
$calculateHeight->MultiCell($this->firstColumnWidth, 3, $item['description'], 0, 'L', 1);
$descriptionHeight = $calculateHeight->getY() + $cellHeight + 2;

因此,他从字面上创建了一个“临时”PDF,添加了多单元格,然后简单地测量高度(newY - oldY)

另外,请记住,如果文本换行 - 单元格的高度将为 = number_of_lines * $height(作为第二个参数传递给 MultiCell 的高度)

因此,如果您将 5 作为 $height 传递,并且临时 PDF 测量该单元格将为 15,您可以确定文本将扩展到 3 行。

于 2019-02-05T11:32:04.960 回答
0

当您打印出文本时,简单地不使用寄宿生会不会更容易。

你可以只使用 $pdf->GetY(); 得到当前的 y 值。

然后当你打印完所有文本后,你可以使用 $pdf->GetY(); 获取每段文本之后的高度。比较 y 值以查看哪个值最大。

那么你需要做的就是 $pdf-> SetY($y); 到原始 y 值并使用 $pdf->Cell() 绘制边界,因为您知道高度和宽度;

我就是这样做的。

编辑:测试它,似乎工作。现在和我一起唱歌——“你得到了两全其美……”不是吗?

$cellData = array();
$cellData[0] = array();
$cellData[0][0] = array();
$cellData[0][0]['text'] = 'Audiometry';
$cellData[0][0]['width'] = '47';

$cellData[0][1] = array();
$cellData[0][1]['text'] = 'Control of Noise at Work Regulations 2005.';
$cellData[0][1]['width'] = '47';

$cellData[0][2] = array();
$cellData[0][2]['text'] = 'Fit with restrictions (as detailed below) to work in a noise controlled zone.';
$cellData[0][2]['width'] = '47';

$cellData[0][3] = array();
$cellData[0][3]['text'] = 'Recommended review date: 2021-11-27

Referral: Referred to OHP';
$cellData[0][3]['width'] = '47';

setAllCellSizes($cellData, $pdf);

function setAllCellSizes($cellData, $pdf){
$y = $pdf->GetY();
$x = $pdf->GetX();

$largestCell = 0;
for($cordI = 0; $cordI < count($cellData); $cordI++){
    $curX = 10;
    for($cordJ = 0; $cordJ < count($cellData[$cordI]); $cordJ++){
        $pdf->SetXY($curX,$y);
        $pdf-> MultiCell($cellData[$cordI][$cordJ]['width'], 5, $cellData[$cordI][$cordJ]['text'], '0', 'L');
        $curX = $curX + $cellData[$cordI][$cordJ]['width'];

        $cellHeight = $pdf->GetY() - $y;

        if($largestCell < $cellHeight){
            $largestCell = $cellHeight;
        }
    }

    $curX = 10;
    for($cordJ = 0; $cordJ < count($cellData[$cordI]); $cordJ++){
        $pdf->SetXY($curX,$y);
        $pdf->Cell($cellData[$cordI][$cordJ]['width'],$largestCell,'',1,1,'L');
        $curX = $curX + $cellData[$cordI][$cordJ]['width'];
    }
}

return $cellData;
}
于 2021-11-27T04:43:07.627 回答