複数ページのPDFを作成しようとしていますが、ページ分割に備えるために、個々の要素(MultiCell)の高さを事前に計算する必要があります。ドキュメントによると、GetCharWidth / GetStringWidthのように、自分でそれを実行するのをサポートする関数がいくつかありますが、パフォーマンスが失われる可能性があることに加えて、とにかく正しく実行しないでしょう。よりエレガントな方法で私の目標を達成するための提案?
参照:TCPDF
私はそれを手に入れました:D!!!!!
別の pdf2 オブジェクトを作成する
// pdf2 set x margin to pdf1's xmargin, but y margin to zero
// to make sure that pdf2 has identical settings, you can clone the object (after initializing the main pdf object)
$pdf2 = clone $pdf;
pdf2->addpage
pdf2->writeCell
$height = pdf2->getY()
pdf2->deletePage(pdf2->getPage())
pdf1->checkPageBreak($height);
pdf1->writeCell()
W00tness :D
これは古い質問ですが、TCPDF の現在のバージョン (2011 年 12 月 7 日現在) には、getStringHeight
実際に MultiCell を呼び出す前に、MultiCell に渡された文字列の結果の高さを計算できる関数が呼び出されています。次に、この高さは、さまざまなこと、元の質問の計算、およびテーブルなどを作成するときの行の高さの設定にも使用できます。うまく機能します。
私が行ったように、この問題の解決策を探している他の誰かがこの質問に出くわした場合の情報です。
私の経験から、セルの高さを事前に把握することはほぼ不可能です。改ページに向かっているかどうかを事前に知らせる、TCPDF の改ページ処理関数を使用する方がはるかに簡単です。コード例は次のとおりです。
$yy = $this->pdf->GetY();
$check_pagebreak = $this->pdf->checkPageBreak($height+$padding,$yy,false);
false を true に変更して、自動改ページを許可します。それ以外の場合は、改ページのロジックを自分で処理できます。これが私が最終的に行ったことです。
また、これが必要な場合に備えて、もう 1 つのちょっとしたヒントがあります。トランザクション機能を使用して、2 つのパスでドキュメントを作成することを検討してください。最初のパスは、すべての高さとセル、改ページなどを把握するために使用されます。また、すべての行の高さとページごとの行を配列に格納することもできます。2 番目のパスでは、すべての正しい情報を使用してドキュメントを作成し、改ページ ロジックは必要ありません (2 番目のパスは、コードを読みやすくし、正気を保つために、別のメソッドから実行できます)。
TCPDF の使用例 20
セル/列が異なるページで終了する場合、MultiCell の高さの計算は悪夢になる可能性があります。
トランザクションまたは追加の pdf オブジェクトを使用すると、処理が非常に遅くなる可能性があります。
getNumLines() や getStringHeight() などの関数を使用して、セルが印刷される前に「推定」(ドキュメントを参照) の高さを計算しても、常に正しく機能するとは限りません。特に、テキストがセルの右枠の直前または直後で終わっている場合は、行が重なり合って印刷されます。
私は、例 20で使用されている、異なるページの最大 Y 値を使用して新しい行の位置を計算する手法を好みます。
この例では 2 列しか出力されませんが、メイン関数を変更して、列の配列を出力できるようにしました。明らかに、各列のフォント、境界線などのデータを配列に追加できます。
public function MultiRow($columnsArray) {
$page_start = $this->getPage();
$y_start = $this->GetY();
$pageArray = array();
$yArray = array();
// traverse through array and print one column at a time.
$columnCount = count($columnsArray);
for($i=0; $i<$columnCount; $i++)
{
if($i+1 < $columnCount)
{
// Current column is not the last column in the row.
// After printing, the pointer will be moved down to
// the right-bottom of the column - from where the
// next multiCell in the following loop will use it
// via $this->GetX().
$ln = 2;
}
else
{
// Current column is the last column in the row.
// After printing, the pointer will be moved to new line.
$ln = 1;
}
$this->MultiCell(30, 0, $columnsArray[$i], 1, 'L', 1, $ln,
$this->GetX() ,$y_start, true, 0);
$pageArray[$i] = $this->getPage();
$yArray[$i] = $this->GetY();
// Go to page where the row started - to print the
// next column (if any).
$this->setPage($page_start);
}
// Test if all columns ended on the same page
$samePage = true;
foreach ($pageArray as $val) {
if($val != $pageArray['0'])
{
$samePage = false;
break;
}
}
// Set the new page and row position by case
if($samePage == true)
{
// All columns ended on the same page.
// Get the longest column.
$newY = max($yArray);
}
else
{
// Some columns ended on different pages.
// Get the array-keys (not the values) of all columns that
// ended on the last page.
$endPageKeys = array_keys($pageArray, max($pageArray));
// Get the Y values of all columns that ended on the last page,
// i.e. get the Y values of all columns with keys in $endPageKeys.
$yValues = array();
foreach($endPageKeys as $key)
{
$yValues[] = $yArray[$key];
}
// Get the largest Y value of all columns that ended on
// the last page.
$newY = max($yValues);
}
// Go to the last page and start at its largets Y value
$this->setPage(max($pageArray));
$this->SetXY($this->GetX(),$newY);
}
Revisited: Tcpdf – Variable Height Table Rows With MultiCellには、多くの有用な情報があります。これは短い抜粋です:
getNumLines()
...実際には、特定の幅が与えられた場合に、テキストの文字列が占める行数を決定できます。実際には、実際には何も描画せずに、MultiCell を使用して返していたことを行うことができます。これにより、1 行のコードでセルの最大高さを決定できます。$linecount = max($pdf->getNumLines($row['cell1data'], 80),$pdf->getNumLines($row['cell2data'], 80