コンテンツの量が異なる同じ高さで fpdf マルチセルを表示する方法
7 に答える
素晴らしい質問です。
マルチセル化される行のデータの各セルを調べて、これらすべてのセルの最大の高さを決定することで、問題を解決しました。これは、行に最初のセルを作成する前に発生し、実際にレンダリングするときに行の新しい高さになります。
1つのセルでこれを実現するためのいくつかの手順を次に示しますが、すべてのマルチセルでこれを行う必要があります。
$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.
$column_width
セルパディングの一種として、から1を引きました。それはより良い結果を生み出しました。結果の複数行セルの高さを決定します。
$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.
$row_height
を最大に設定して、他のマルチセルセルに対してこの方法を繰り返し$height_of_cell
ます。$row_height
最後に、行の高さを使用して行をレンダリングします。
コンテンツが半分または1行と半分の行であっても、高さを3行に等しくする必要がある場合にも同じ問題が発生していました。 1 行以下の文字がない場合、2 行の空行に対して ln() が呼び出され、2 行文字以下の単語がない場合、1 つの 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);
}
まず、Multicell の高さを求めることは問題ではありません。(@Matias、@Josh Pinterへ)
このコードを2行以上使用するように@Balram Singhの回答を修正しました。マルチセルの高さを固定するために新しい行 (\n) を追加しました。お気に入り..
$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() を割り当てる必要があります。
わかりました、再帰バージョンを実行しました。これが原因にさらに役立つことを願っています!次の変数を考慮してください。
$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--
楽しみ!
私のアプローチはとてもシンプルでした。fpdf クラスの header() と footer() をオーバーライドする必要があります。だから私は関数を追加しましたMultiCellLines($w, $h, $txt, $border=0, $align='J', $fill=false)
。これは、元の MultiCell の非常に単純なコピーです。ただし、何も出力せず、行数を返すだけです。
行に行の高さを掛ければ安全です;)私のコードのダウンロードはこちらです。
名前を「.php」または好きなものに戻してください。楽しむ。それは間違いなく機能します。
マック
より良い解決策は、独自のワード ラップ機能を使用することです。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;
}
これは、内破/結合を使用してマージできるテキスト行の配列を返します。
join("\r\n", $lines);
そして、それが最初に使用された目的は、行の高さを取得することです:
$lineHeight = count($lines) * $multiCellLineHeight;
これは、スペース文字を含む文字列でのみ機能し、タブのような空白はありません。次に、 strpos を正規表現関数に置き換えることができます。
プリセットボックスに従ってフォントサイズと行間を縮小する私の個人的な解決策:
// 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');
それで全部です!