使用FPDF导出MySQL数据为PDF时表格单元格内容无法适配问题求助
问题根因
你当前代码出现表格内容无法适配单元格的核心原因有两个:
- 所有单元格强制写死了24单位的宽度,未根据不同列的实际内容长度动态调整
- 使用
Cell()方法输出内容,原生Cell()不支持自动换行,超出固定宽度的内容会直接溢出单元格
修复后的完整代码
<?php require('./fpdf/fpdf.php'); // 数据库配置 require_once __DIR__ . '/db_config.php'; $connection = mysqli_connect(DB_SERVER,DB_USER,DB_PASSWORD,DB_DATABASE); if(!$connection){ die("Connection error : " . mysqli_connect_error()); } class PDF extends FPDF { // 页头 function Header() { $ImagePath ='image url'; // 调整Logo位置到顶部左上角,避免遮挡表格 $this->Image($ImagePath,10,10,30); $this->SetFont('Arial','B',13); // 移动到中间输出标题 $this->Cell(80); $this->Cell(80,10,'title',1,0,'C'); // 换行 $this->Ln(20); } // 页脚 function Footer() { // 距离底部1.5cm $this->SetY(-15); $this->SetFont('Arial','I',8); // 页码 $this->Cell(0,10,'Page '.$this->PageNo().'/{nb}',0,0,'C'); } // 输出自适应行高的表格行 function Row($data, $widths) { $maxHeight = 0; // 先计算本行最高的单元格高度 for($i=0; $i<count($data); $i++){ $nbLines = $this->NbLines($widths[$i], $data[$i]); $height = 7 * $nbLines; if($height > $maxHeight) $maxHeight = $height; } // 输出每个单元格 for($i=0; $i<count($data); $i++){ $x = $this->GetX(); $y = $this->GetY(); // 画单元格边框 $this->Rect($x, $y, $widths[$i], $maxHeight); // 输出内容 $this->MultiCell($widths[$i], 7, $data[$i], 0, 'C'); // 移动到下一个单元格位置 $this->SetXY($x + $widths[$i], $y); } // 移动到下一行 $this->Ln($maxHeight); } // 计算文本需要的行数 function NbLines($width, $text) { $cw = $this->CurrentFont['cw']; if($width == 0) $width = $this->w - $this->lMargin - $this->rMargin; $wmax = ($width - 2*$this->cMargin) * 1000 / $this->FontSize; $text = str_replace("\r", '', $text); $nb = strlen($text); if($nb > 0 && $text[$nb-1] == "\n") $nb--; $sep = -1; $i = 0; $j = 0; $l = 0; $nl = 1; while($i < $nb) { $c = $text[$i]; if($c == "\n") { $i++; $sep = -1; $j = $i; $l = 0; $nl++; continue; } if($c == ' ') $sep = $i; $l += $cw[$c]; if($l > $wmax) { if($sep == -1) { if($i == $j) $i++; } else $i = $sep+1; $sep = -1; $j = $i; $l = 0; $nl++; } else $i++; } return $nl; } } // 列名映射 $display_heading = array( 'JobId'=>'JobId', 'ReleaseDate'=>'ReleaseDate', 'StartingDate'=>'StartingDate', 'TargetTime'=>'TargetTime', 'JobContent'=>'JobContent', 'KindId'=>'KindId', 'JobStatus'=>'JobStatus', 'CustomerId'=>'CustomerId' ); // 读取数据 $result = mysqli_query($connection, "SELECT * FROM Jobs;") or die("database error:". mysqli_error($connection)); $headerRes = mysqli_query($connection, "SHOW columns FROM Jobs"); $headers = []; while($h = mysqli_fetch_assoc($headerRes)){ $headers[] = $display_heading[$h['Field']]; } $rows = []; while($r = mysqli_fetch_assoc($result)){ $rows[] = array_values($r); } // 计算每列最大宽度 $pdf = new PDF(); $pdf->SetFont('Arial','B',8); $widths = array_fill(0, count($headers), 0); // 先算表头宽度 foreach($headers as $k => $h){ $w = $pdf->GetStringWidth($h) + 6; // 加边距 if($w > $widths[$k]) $widths[$k] = $w; } // 再算所有行内容宽度 foreach($rows as $row){ foreach($row as $k => $v){ // 长内容列限制最大宽度,比如JobContent是第4列(索引从0开始),限制最大宽度60 if($k == 4){ $w = 60; }else{ $w = $pdf->GetStringWidth($v) + 6; } if($w > $widths[$k]) $widths[$k] = $w; } } // 生成PDF $pdf->AddPage(); $pdf->AliasNbPages(); // 输出表头 $pdf->Row($headers, $widths); // 输出数据行 foreach($rows as $row){ $pdf->Row($row, $widths); } $pdf->Output(); // 关闭连接 mysqli_close($connection); ?>
可选调整项
- 如果页面宽度不够,可以改为横向A4纸,实例化PDF时改为
new PDF('L','mm','A4') - 可以根据实际需求调整各列的最大宽度限制,当前代码仅限制了JobContent列最大宽度为60
- 如果需要使用中文字体,需要自行导入支持中文的字体替换Arial
内容的提问来源于stack exchange,提问作者Cemal Tüysüz
相关产品推荐
相关产品推荐

