简体   繁体   English

是否可以使TCPDF元素具有最大高度?

[英]Is it possible to make a TCPDF element with maximum height?

I'm working with TCPDF using PHP. 我正在使用PHP使用TCPDF。 I'm trying to make a PDF document that must be only one page long. 我试图让那一定是只有一页长的PDF文档。 This document includes a table, the data of which has a dynamically determined number of rows. 该文档包括一个表,该表的数据具有动态确定的行数。

What I'd like to do is to give this table a maximum height (eg 10 cm), and to shrink the font size of the table if it goes over this limit. 我想做的就是给这张桌子一个最大的高度(例如10厘米),如果桌子的字体超过这个限制,要缩小它的字体大小。 That way the data is still there, but the document will fit on the one page. 这样,数据仍然存在,但是文档将适合一页。 Is this possible? 这可能吗? I've tried using the WriteHTML() method, but it seems to ignore the height I give it. 我尝试使用WriteHTML()方法,但似乎忽略了我给它的高度。 (That is, if the data goes over, it just keeps writing rather than cutting it off.) (也就是说,如果数据结束,它只会继续写入而不是切断数据。)

Is this possible? 这可能吗?

One way to do this would be to set the size of individual MultiCell or Cell outputs. 一种方法是设置单个MultiCellCell输出的大小。 There's a lot of visual tweaking involved, but you can get pretty precise. 涉及很多视觉调整,但是您可以非常精确地进行调整。 I created a rough example with fixed line heights for simplicity's sake. 为了简单起见,我创建了一个具有固定行高的粗略示例。 Basically the idea would be to set your maximum height and place (Multi)Cells to the right of the previous one with the $ln parameter set to 0. (Or set the coordinates before each call.) You can see an example output file here: https://s3.amazonaws.com/rrbits/maxheight.pdf 基本上,这个想法是在$ln参数设置为0的情况下,将最大高度和位置(Multi)Cells设置在上一个(Multi)Cells的右侧。(或在每次调用之前设置坐标。)您可以在此处看到示例输出文件: https//s3.amazonaws.com/rrbits/maxheight.pdf

MultiCell has an autofit setting that'll handle scaling the fonts down for you, which I use in the MultiCell example. MultiCell具有autofit设置,该设置将为您处理字体的缩小,我在MultiCell示例中使用了该MultiCell A potential caveat is that it will allow wrapping. 一个潜在的警告是它将允许包装。

Cell doesn't have an autofit parameter, but you can simulate it by setting the font size to a sane maximum, check the cell string's width with GetStringWidth and reducing the font size until it fits. Cell没有autofit参数,但是您可以通过将字体大小设置为合理的最大值来模拟它,使用GetStringWidth检查单元格字符串的宽度并减小字体大小直到适合为止。 [Edit: I don't do it here, but it'd be a good idea to restore the font size after outputting your cell or you could have some unexpected results.] (see the loop on line 105). [编辑:我这里不做,但是在输出单元格之后恢复字体大小是个好主意,否则您可能会得到一些意想不到的结果。](请参见第105行的循环)。 ( Cell does have some font stretching options available, see TCPDF example 004 , but they didn't quite do what you were asking.) Cell确实有一些字体扩展选项可用,请参阅TCPDF示例004 ,但它们并没有完全按照您的要求进行。)

<?php
require_once('TCPDF-6.2.17/tcpdf.php');
// create new PDF document
$pdf = new TCPDF('L', 'mm', array(130,130), true, 'UTF-8', false);

$pdf->SetFont('times', '', 8);
$pdf->SetAutoPageBreak(TRUE, 5);

//Generating a random table for testing.
$table = [
  ['Name','Description','md5'],
];
$rows = rand(10,30);
//$rows = rand(3,5);
for($i = 0; $i < $rows; $i++) {
  $table[] = array(
    'Sector '.rand(1,10000),
    str_repeat('An Apple', rand(2,6)),
    md5(rand(1,100000)),
  );
}

$pdf->addPage();

$pdf->Write(2, 'MultiCell Example');
$pdf->Ln();
$pdf->SetFont('times', '', 8);

$column_widths = array(
  20,
  60,
  30,
);

//Total table should only be 10cm tall.
$maxheight = 100/count($table);
if($maxheight > 10) {
  $maxheight = 10;
}
foreach($table as $index => $row) {
  if($index == 0) {
    $pdf->SetFillColor(230,230,255);
  } else {
    if( ($index&1) == 0 ) {
      $pdf->SetFillColor(210,210,210);
    } else {
      $pdf->SetFillColor(255,255,255);
    }
  }
  $pdf->SetX(10);
  $currenty = $pdf->GetY();
  foreach($row as $index => $column) {
    $pdf->MultiCell(
      $width = $column_widths[$index],
      $minheight = $maxheight,
      $text = $column,
      $border = 'B', //Border bottom
      $align = 'L',
      $fill = true,
      $ln = 0, //Move to right after cell.
      $x = null,
      $y = null,
      $reseth = true,
      $stretch = 0,
      $ishtml = false,
      $autopadding = true,
      $maxheight,
      $valign = 'T',
      $fitcell = true);
  }
  $pdf->SetY($currenty + $maxheight);
}

$pdf->addPage();

$pdf->SetFont('times', '', 8);
$pdf->Write(2, 'Cell Example');
$pdf->Ln();
$pdf->SetFont('times', '', 8);

$maxheight = 100/count($table);
if($maxheight > 8) {
  $maxheight = 8;
}

$maxfontsize = 10;
$pdf->SetFontSize($maxfontsize);

foreach($table as $index => $row) {
  if($index == 0) {
    $pdf->SetFillColor(230,230,255);
  } else {
    if( ($index&1) == 0 ) {
      $pdf->SetFillColor(210,210,210);
    } else {
      $pdf->SetFillColor(255,255,255);
    }
  }
  $pdf->SetX(10);
  $currenty = $pdf->GetY();
  foreach($row as $index => $column) {
    //Reduce the font size to fit properly.
    $pdf->SetFontSize($csize = $maxfontsize);
    //0.2 step down font until it fits the cell.
    while($pdf->GetStringWidth($column) > $column_widths[$index]-1 ) {
      $pdf->SetFontSize($csize -= 0.2);
    }
    $pdf->Cell(
      $width = $column_widths[$index],
      $cellheight = $maxheight,
      $text = $column,
      $border = 'B', //Border bottom
      $ln = 0,
      $align = 'L',
      $fill = true,
      $stretch = 1,
      $ignore_min_height = true,
      $calign = 'T',
      $valign = 'T');
  }
  $pdf->SetY($currenty + $maxheight);
}

$pdf->Output(dirname(__FILE__).'/maxheight.pdf', 'F');

Addendum: Alternative method with WriteHTML 附录: WriteHTML替代方法

A way you could do this with WriteHTML is to start a transaction with startTransaction , set a base font for the entire table and write the HTML, then check the number of pages. 使用WriteHTML可以实现的一种方法是,使用startTransaction启动事务,为整个表设置基本字体并编写HTML,然后检查页面数。 If you encounter an automatic page break, roll back the transaction and try with a smaller font size. 如果遇到自动分页符,请回滚事务并尝试使用较小的字体。 Otherwise commit the transaction. 否则,提交事务。

I've updated the link above with the output from this as an example: 作为示例,我已经使用上面的输出更新了上面的链接:

//Example with WriteHTML.
$pdf->AddPage();
$pdf->SetFont('times', '', 8);
$pdf->Write(2, 'WriteHTML Example');
$pdf->Ln();
$pdf->SetFont('times', '', 8);

//Max height of 100 mm.
$maxy = $pdf->GetY()+100;
$fontsize = 14;
//Make table markup.
$tablehtml = '<table cellspacing="2" style="font-family: times; font-size:_FONTSIZE_px;">';
foreach($table as $index => $row) {
  if($index == 0) {
    $rowstyle = ' background-color: rgb(230,230,255); '.
      'font-size: 110%; font-familt: times; font-weight: bold;'.
      'border-bottom: 1px solid black;';
  } else {
    if( ($index&1) == 0 ) {
      $rowstyle = 'background-color: rgb(210,210,210);';
    } else {
      $rowstyle = 'background-color: white;';
    }
  }
  $tablehtml .= "<tr style=\"$rowstyle\">";
  foreach($row as $column) {
    $tablehtml .= "<td>$column</td>";
  }
  $tablehtml .= '</tr>';
}
$tablehtml .= '</table>';

//Transaction loop.
$numpages = $pdf->getNumPages();
$done = false;
while(!$done) {
  $pdf->startTransaction(true);
  $pdf->SetFont('times', '', 14);
  $outtable = str_replace('_FONTSIZE_', $fontsize, $tablehtml);
  $pdf->writeHTML($outtable);
  if($pdf->getNumPages() > $numpages || $pdf->GetY() > $maxy) {
    //If we encountered a page break or exceeded the desired maximum height
    //rollback the transaction.
    $pdf->rollbackTransaction(true);
    $fontsize -= 0.4;
    //Larger font steppings will be less precise, but faster.
  } else {
    $pdf->commitTransaction(true);
    $done = true;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM