我们如何以相同的高度显示具有不同内容量的 fpdf 多单元格
7 回答
好问题。
我通过遍历行中的每个单元格数据来解决它,这些单元格将被多单元格并确定所有这些单元格的最大高度。这发生在您在行中创建第一个单元格之前,当您实际渲染它时,它会成为行的新高度。
以下是仅针对一个单元格实现此目的的一些步骤,但您需要为每个多单元格执行此操作:
这假定一个$row
具有名为的字符串属性的数据description
。
首先,获取单元格内容并设置单元格的列宽。
$description = $row['desciption']; // MultiCell (multi-line) content. $column_width = 50;
description
使用以下GetStringWidth()
函数获取字符串的宽度FPDF
:$total_string_width = $pdf->GetStringWidth($description);
确定此单元格的行数:
$number_of_lines = $total_string_width / ($column_width - 1); $number_of_lines = ceil( $number_of_lines ); // Round it up.
我从 中减去 1
$column_width
作为一种单元格填充。它产生了更好的结果。确定生成的多行单元格的高度:
$line_height = 5; // Whatever your line height is. $height_of_cell = $number_of_lines * $line_height; $height_of_cell = ceil( $height_of_cell ); // Round it up.
对任何其他 MultiCell 单元重复此方法,将 设置
$row_height
为最大的$height_of_cell
.最后,使用
$row_height
你的行高来渲染你的行。
好的,我已经完成了递归版本。希望这对事业有更大的帮助!考虑这些变量:
$columnLabels:每列的标签,因此您将在每列后面存储数据) $alturasFilas:存储每行最大高度的数组。
//Calculate max height for each column for each row and store the value in //////an array
$height_of_cell = 0;
$alturasFilas = array();
foreach ( $data as $dataRow ) {
for ( $i=0; $i<count($columnLabels); $i++ ) {
$variable = $dataRow[$i];
$total_string_width = $pdf->GetStringWidth($variable);
$number_of_lines = $total_string_width / ($columnSizeWidth[$i] - 1);
$number_of_lines = ceil( $number_of_lines ); // Redondeo.
$line_height = 8; // Altura de fuente.
$height_of_cellAux = $number_of_lines * $line_height;
$height_of_cellAux = ceil( $height_of_cellAux );
if($height_of_cellAux > $height_of_cell){
$height_of_cell = $height_of_cellAux;
}
}
array_push($alturasFilas, $height_of_cell);
$height_of_cell = 0;
}
//--END--
享受!
首先,获取Multicell的高度不是问题。(致@Matias,@Josh Pinter)
我修改了@Balram Singh 的答案,将此代码用于两行以上。我添加了新行 (\n) 来锁定 Multicell 的高度。喜欢..
$cell_width = 92; // Multicell width in mm
$max_line_number = 4; // Maximum line number of Multicell as your wish
$string_width = $pdf->GetStringWidth($data);
$line_number = ceil($string_width / $cell_width);
for($i=0; $i<$max_line_number-$line_number; $i++){
$data.="\n ";
}
当然你必须在使用 GetStringWidth() 之前分配 SetFont()。
当我必须将高度等于三行时,我也遇到了同样的问题,即使我的内容是一半或 1 和半行,我通过检查字符串中的元素数量是否小于一行中可能的字母来解决这个问题它是 60。如果没有字母小于或等于 1 行,则调用 ln() 来处理两个空行,如果没有单词等于或小于 2 行字母,则调用 ln()。我的代码在这里:
$line_width = 60; // Line width (approx) in mm
if($pdf->GetStringWidth($msg1) < $line_width)
{
$pdf->MultiCell(75, 8, $msg1,' ', 'L');
$pdf->ln(3);
$pdf->ln(3.1);
}
else{
$pdf->MultiCell(76, 4, $msg1,' ', 'L');
$pdf->ln(3.1);
}
我的方法很简单。您已经需要覆盖 fpdf 类中的 header() 和 footer()。所以我只是添加了一个功能MultiCellLines($w, $h, $txt, $border=0, $align='J', $fill=false)
。这是原始 MultiCell 的一个非常简单的副本。但它不会输出任何东西,只是返回行数。
将行乘以您的行高,您就安全了;)我的代码下载在这里。
只需将其重命名为“.php”或您喜欢的任何名称。玩得开心。它肯定有效。
苹果电脑
我个人根据预设框减小字体大小和行距的解决方案:
// set box size and default font size
$textWidth = 100;
$textHeight = 100;
$fontsize = 12;
// if you get text from html div (using jquery and ajax) you must replace every <br> in a new line
$desc = utf8_decode(str_replace('<br>',chr(10),strip_tags($_POST['textarea'],'<br>')));
// count newline set in $desc variable
$countnl = substr_count($desc, "\n");
// Create a loop to reduce the font according to the contents
while($pdf->GetStringWidth($desc) > ($textWidth * (($textHeight-$fontsize*0.5*$countnl) / ($fontsize*0.5)))){
$fontsize--;
$pdf->SetFont('Arial','', $fontsize);
}
// print multicell and set line spacing
$pdf->MultiCell($textWidth, ($fontsize*0.5), "$desc", 0, 'L');
就这样!
更好的解决方案是使用您自己的自动换行功能,因为 FPDF 不会剪切单词,因此您不必依赖 MultiCell 换行符。
如果 FPDF 的 getStringWidth 大于列宽,我编写了一个方法来检查文本的每个子字符串,并相应地进行拆分。如果您更关心美观的 PDF 布局而不是性能,这将非常棒。
public function wordWrapMultiCell($text, $cellWidth = 80) {
$explode = explode("\n", $text);
array_walk($explode, 'trim');
$lines = [];
foreach($explode as $split) {
$sub = $split;
$char = 1;
while($char <= strlen($sub)) {
$substr = substr($sub, 0, $char);
if($this->pdf->getStringWidth($substr) >= $cellWidth - 1) { // -1 for better getStringWidth calculating
$pos = strrpos($substr, " ");
$lines[] = substr($sub, 0, ($pos !== FALSE ? $pos : $char)).($pos === FALSE ? '-' : '');
if($pos !== FALSE) { //if $pos returns FALSE, substr has no whitespace, so split word on current position
$char = $pos + 1;
$len = $char;
}
$sub = ltrim(substr($sub, $char));
$char = 0;
}
$char++;
}
if(!empty($sub)) {
$lines[] = $sub;
}
}
return $lines;
}
这将返回一个文本行数组,您可以使用 implode/join 将其合并:
join("\r\n", $lines);
以及它最初的用途,获取行高:
$lineHeight = count($lines) * $multiCellLineHeight;
这仅适用于带有空格字符的字符串,没有制表符之类的空白。然后,您可以用正则表达式函数替换 strpos 。