многоклеточный выпуск fpdf - PullRequest
13 голосов
/ 17 ноября 2009

как мы отображаем многоклеточный fpdf на равных высотах с разным количеством контента

Ответы [ 7 ]

15 голосов
/ 23 апреля 2010

Отличный вопрос.

Я решил эту проблему, пройдя каждую ячейку данных в строке, которая будет многоклеточной, и определив наибольшую высоту из всех этих ячеек. Это происходит за до того, как вы создадите свою первую ячейку в строке, и она станет новой высотой вашей строки, когда вы фактически начнете ее визуализировать.

Вот несколько шагов для достижения этого только для одной ячейки, но вам нужно будет сделать это для каждой многоклеточной ячейки:

Это предполагает $row данных с атрибутом String с именем 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.
    

    Я вычел 1 из $column_width как вид заполнения ячеек. Это дало лучшие результаты.

  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.

0 голосов
/ 21 января 2016

Лучшим решением было бы использовать собственную функцию переноса слов, поскольку FPDF не будет обрезать слова, поэтому вам не нужно полагаться на разрыв строки MultiCell.

Я написал метод, который проверяет каждую подстроку текста, является ли getStringWidth FPDF больше ширины столбца, и разделяется соответствующим образом. Это замечательно, если вам важнее красивый макет 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 функцией регулярного выражения.

0 голосов
/ 06 июня 2015

Мое личное решение для уменьшения размера шрифта и межстрочного интервала в соответствии с предустановкой:

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

Вот и все!

0 голосов
/ 05 июня 2015

Мой подход был довольно прост. Вам уже нужно переопределить header () и footer () в классе fpdf. Поэтому я просто добавил функцию MultiCellLines($w, $h, $txt, $border=0, $align='J', $fill=false). Это очень простая копия оригинальной MultiCell. Но он ничего не выведет, просто вернет количество строк.

Умножьте строки на вашу высоту строки, и вы в безопасности;) Скачать для моего кода здесь .

Просто переименуйте его обратно в ".php" или как хотите. Повеселись. Это работает определенно.

Mac

0 голосов
/ 20 февраля 2015

Во-первых, вопрос не в том, чтобы получить высоту 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 ";
}

Конечно, вы должны назначить SetFont () перед использованием GetStringWidth ().

0 голосов
/ 13 февраля 2015

Хорошо, я сделал рекурсивную версию. Надеюсь, это поможет еще больше делу! Примите во внимание эти переменные:

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

Наслаждайтесь!

0 голосов
/ 22 ноября 2012

У меня также возникала такая же проблема, когда мне приходилось устанавливать высоту равной трем строкам, даже если у меня было содержимое половины или 1 и половины строки, я решил эту проблему, проверив, нет ли в строке ни одного элемента из возможных букв. в строке это 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);
}
...