fpdf多单元问题

时间:2009-11-17 11:14:08

标签: fpdf

我们如何在具有不同内容量的相等高度显示fpdf多单元

7 个答案:

答案 0 :(得分:15)

很棒的问题。

我通过遍历您的行中将被多线化的每个数据单元来解决它,并确定所有这些单元格的最大高度。这种情况发生在之前你在行中创建了第一个单元格,当你真正去渲染它时它就成了你行的新高度。

以下是针对一个单元实现此目的的一些步骤,但您需要为每个多单元执行此操作:

这假设$row数据具有名为description的字符串属性。

  1. 首先,获取单元格内容并设置单元格的列宽。

    $description = $row['desciption'];           // MultiCell (multi-line) content.
    
    $column_width = 50;
    
  2. 使用description中的GetStringWidth()函数获取FPDF字符串的宽度:

    $total_string_width = $pdf->GetStringWidth($description);
    
  3. 确定此单元格的行数:

    $number_of_lines = $total_string_width / ($column_width - 1);
    
    $number_of_lines = ceil( $number_of_lines );  // Round it up.
    

    我从$column_width中减去1作为一种细胞填充。它产生了更好的结果。

  4. 确定生成的多行单元格的高度:

    $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.
    
  5. 对任何其他MultiCell单元格重复此方法,将$row_height设置为最大$height_of_cell

  6. 最后,使用$row_height为行的高度渲染行。

  7. <强> Dance.

答案 1 :(得分:0)

当我必须将高度等于三行时,我也得到同样的问题,即使我有一半或一半半的内容,我通过检查字符串中是否有少于可能的字母来解决这个问题在一行中它是60.如果没有字母小于或等于一行,那么对于两个空行调用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);
}

答案 2 :(得分:0)

好的,我已经完成了递归版本。希望这有助于更多的事业! 考虑这些变量:

$ 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-- 

享受!

答案 3 :(得分:0)

首先,获得Multicell的高度不是问题。 (致@Matias,@ Josh Pinter)

我修改了@Balram Singh的答案,将此代码用于2行以上。 我添加了新行(\ 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()。

答案 4 :(得分:0)

我的方法非常简单。您已经需要覆盖fpdf类中的header()和footer()。 所以我刚添加了一个函数MultiCellLines($w, $h, $txt, $border=0, $align='J', $fill=false)。 这是原始MultiCell的一个非常简单的副本。但它不会输出任何东西,只返回行数。

将线条与线高相乘,您就安全了;) 我的代码下载为here

只需将其重命名为“.php”或任何您喜欢的内容。玩得开心。它绝对有效。

的Mac

答案 5 :(得分:0)

我个人解决方案,根据预设框减少字体大小和行间距:

// 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');

这就是全部!

答案 6 :(得分:0)

更好的解决方案是使用自己的自动换行功能,因为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。