Is there an easy way to wrap a string inside a cell table in FPDF? I found a couple of answers but they look a little hard coded. I am retrieving data from my database so need it to by dynamic.
Here is an image showing my progress so far. The text is overlapping, so I need to get the cells to grow in height as required.
SAMPLE CODE
$row_height = 6;
$header = 35;
$y_axis = $header + $row_height;
while($row = mysqli_fetch_assoc($result)) {
$col1= $row['col1'];
$col2= $row['col2'];
$col3= $row['col3'];
if ($y_axis >= 275) { // new page
$pdf->AddPage();
tableHeader($pdf);
$y_axis = $header + $row_height;
}
//List of items
$pdf->SetFont('Arial','',8);
$pdf->SetY($y_axis);
$pdf->SetX(10);
$pdf->MultiCell(40,$row_height,$col1,1);
$pdf->SetY($y_axis);
$pdf->SetX(50);
$pdf->MultiCell(60,$row_height,$col2,1);
$pdf->SetY($y_axis);
$pdf->SetX(110);
$pdf->MultiCell(90,$row_height,$col3,1);
$y_axis = $y_axis + $row_height;
}
Maybe FPDF's MultiCell method fits your needs.
This method allows printing text with line breaks. They can be automatic (as soon as the text reaches the right border of the cell) or explicit (via the \n character). As many cells as necessary are output, one below the other.
Text can be aligned, centered or justified. The cell block can be framed and the background painted.
Related
I am using FPDF and making table in it using FancyTable example from here http://www.fpdf.org/. Following, I am showing one glimpse of code.
$start_x = $this->GetX(); //initial x (start of column position)
$current_y = $this->GetY();
$current_x = $this->GetX();
$cell_height = 7;
$this->MultiCell($width,$cell_height,$data,0,'L',$fill);
$current_x+=$width; //calculate position for next cell
$this->SetXY($current_x, $current_y);
Output of this is following, You can see one cell data is going outside cell. I have highlighted one cell data that is going outside from cell.
If I increase the height of cell then it seems it increase the line height and not cell height. Following is sample code.
$cell_height = 25;
$this->MultiCell($width,$cell_height,$data,0,'L',$fill);
and output looks like following.
I wrote below code , it working fine but multicell row heights are not working properly.I wrote below code , it working fine but multicell row heights are not working properly.I wrote below code , it working fine but multicell row heights are not working properly.
$x=$pdf->GetY();
$pdf->SetY($x+1);
include_once("config.php");
$result = mysqli_query($mysqli, "SELECT * FROM prd"); // using mysqli_query instead
$i = 1;
while($res = mysqli_fetch_array($result))
{
$current_y = $pdf->GetY();
$current_x = $pdf->GetX();
$pdf->MultiCell(30, 5, $i, 1, 'L');
$end_y = $pdf->GetY();
$prdid = $res[0];
$empid = $res[1];
$specification = $res[2];
$prn = $res[3];
$current_x = $current_x + 30;
$pdf->SetXY($current_x, $current_y);
$pdf->MultiCell(30, 5, $empid, 1, 'L');
$end_y = ($pdf->GetY() > $end_y)?$pdf->GetY() : $end_y;
$current_x = $current_x + 30;
$pdf->SetXY($current_x, $current_y);
$pdf->MultiCell(30, 5, $specification, 1, 'L');
$end_y = ($pdf->GetY() > $end_y)?$pdf->GetY() : $end_y;
$current_x = $current_x + 30;
$pdf->SetXY($current_x, $current_y);
$pdf->MultiCell(30, 5, $prn, 1, 'L');
$end_y = ($pdf->GetY() > $end_y)?$pdf->GetY() : $end_y;
$i++;
$pdf->SetY($end_y);
}
$pdf->Output();
?>
My Result :
How to adjust row height automatically ?
So a multi cell is essentially dynamic is height. The height you put into the function is a "row" height. So what happens is that fpdf goes to write the multi cell and let's say we defined the height to be 5, it'll create a "cell" of height 5 and start writing. Then it hits the hard stop at the width and goes "i have to create a new row", which it then adds a new "cell" of height 5 directly below the top "cell". This repeats until all text is written out. Obviously this is great for dynamic content, but has its own challenges that you have hit.
The path I normally take is to record the start point, write out the multi cell first, and then record the stopping point. You can then go back and write the other cells to make for better alignment. For this GetX, GetY, SetX, SetY will be your friends. You can set heights and such dynamically with simple math.
The "lazy" option is to re-do the layout to allow for the document to scale, that being to take your way too long multi cell and put it UNDER the row so you'll have:
|1 |46 |PR2.....|
|really long text
that will scale
down here|
|2 |........
Hope that helps get you moving forward!
I'm developing an e-Certificate web page.
I've managed loading the certificate template and writing on top of it (Attendee Name, Event Title and Event Date).
But in positioning those three pieces of information, I couldn't position them at the center no matter how long they are. they always start from x point.
Check my work result:
Code:
<?php
require_once('fpdf.php');
require_once('fpdi.php');
$pdf =& new FPDI();
$pdf->addPage('L');
$pagecount = $pdf->setSourceFile('Certificate.pdf');
$tplIdx = $pdf->importPage(1);
$pdf->useTemplate($tplIdx);
$pdf->SetFont('Times','I',18);
$pdf->SetTextColor(0,0,0);
$pdf->SetXY(120, 62);
$pdf->Write(0, "Attendee Name");
$pdf->SetXY(120, 102);
$pdf->Write(0, "Event Name");
$pdf->SetXY(120, 140);
$pdf->Write(0, "Event Date");
$pdf->Output();
?>
Is there away to center the text no matter how long is it?
meaning without fixing the x point. however, the y point result is very good.
So 2 ways I've done this before, the most likely easiest way:
Since you only have 1 entry on the row (Attendee Name or Event Name, etc)
Start a cell at the left most point, and have the cell run the full width of the page, then specify the center option:
$pdf->SetXY(0,62);
//0 extends full width, $height needs to be set to cell height.
$pdf->Cell(0, $height, "Attendee Name", 0, 0, 'C');
The other option is to calculate the center, and set X accordingly:
//how wide is the page?
$midPtX = $pdf->GetPageWidth() / 2;
//now we need to know how long the write string is
$attendeeNameWidth = $pdf->GetStringWidth($attendeeName);
//now we need to divide that by two to calculate the shift
$shiftLeft = $attendeeNameWidth / 2;
//now calculate our new X value
$x = $midPtX - $shiftLeft;
//now apply your shift for the answer
$pdf->setXY($x, 62);
$pdf->Write(0, "Attendee Name");
You can then repeat the above for each of the other elements.
You need a way to calculate the string length in pixels of the string (say, 120 pixels) and you need to know the page width in pixels.
At that point you position the string at x = (pagewidth/2 - stringwidth/2) and Bob's your uncle.
In FPDI you do this with GetStringWidth and GetPageWidth.
You can do the same adjustment with the height. For example you can split the string in words, calculate the width of each one, and determine when it is too much. This way you can split the string in two, and center each section.
I am using fpdf to create pdf from data in MySql table dynamically. And I am printing it using MultiCell() function. My Problem is I want it to auto adjust the line height of the text. I have read the documentation at the site but it only tells about auto adjust width. But I could not find any solution for line height auto adjust. Is there any way to do so. What may be the alternate ways? Please help. Here is the piece of the code. :-
<?php session_start();
include 'conn.php';
$table=$_SESSION["name"];
$testid=$_SESSION["id"];
$stuid=$_SESSION["stuid"];
$ans=$_SESSION["score1"];
//pdf creation
require('../fpdf/fpdf.php');
class PDF extends FPDF
{
function Header()
{
global $title;
$this->Image('../fpdf/logo.JPG',10,10,200);
// Arial bold 15
$this->SetFont('Arial','B',15);
// Calculate width of title and position
$w = $this->GetStringWidth($title)+6;
$this->SetX((210-$w)/2);
// Colors of frame, background and text
// Thickness of frame (1 mm)
$this->SetLineWidth(1);
// Title
// Line break
$this->Ln(20);
}
function Footer()
{
// Position at 1.5 cm from bottom
$this->SetY(-15);
// Arial italic 8
$this->SetFont('Arial','I',8);
// Text color in gray
$this->SetTextColor(128);
// Page number
$this->Cell(0,10,'Page '.$this->PageNo(),0,0,'C');
}
function ChapterTitle($num, $label)
{
// Arial 12
$this->SetFont('Arial','',12);
// Background color
$this->SetFillColor(200,220,255);
// Title
$this->Cell(0,6,"Chapter $num : $label",0,1,'L',true);
// Line break
$this->Ln(4);
}
function ChapterBody($file)
{
// Read text file
$txt = file_get_contents($file);
// Times 12
$this->SetFont('Times','',12);
// Output justified text
$this->MultiCell(0,5,$txt);
// Line break
$this->Ln();
// Mention in italics
$this->SetFont('','I');
$this->Cell(0,5,'(end of excerpt)');
}
function PrintChapter($num, $title, $file)
{
$this->AddPage();
$this->ChapterTitle($num,$title);
$this->ChapterBody($file);
}
}
$pdf = new PDF();
$pdf->SetAuthor('OSP Classes');
$pdf->AddPage();
$x=1;
$i=0;
$sql1=mysql_query("select * from $table") or die (mysql_error());
while($result1=mysql_fetch_row($sql1))
{
$pdf->SetFont('Arial','B',14);
$pdf->MultiCell(0,10,'Ques No.'.$x .'.'. $result1[1]);
$pdf->Ln(10);
$pdf->SetFont('Arial','',14);
$pdf ->MultiCell(0,0,'Ans 1.'. $result1[2]);
$pdf->Ln(10);
$pdf->SetFont('Arial','',14);
$pdf ->MultiCell(0,0,'Ans 2.'. $result1[3]);
$pdf->Ln(10);
$pdf->SetFont('Arial','',14);
$pdf ->MultiCell(0,0,'Ans 3.'. $result1[4]);
$pdf->Ln(10);
$pdf->SetFont('Arial','',14);
$pdf ->MultiCell(0,0,'Ans 4.'. $result1[5]);
$pdf->Ln(10);
$pdf->MultiCell(0,0,'Right Ans . '. $result1[6].' '.'Your Ans . '. $ans[$i]);
$pdf->Ln(20);
$x++;
$i++;
}
$pdf->Output();
?>
Auto line height is not possible in FPDF MultiCell. As This page explains, Multicell creates a cell for each line of text you print. The 2e argument (h) is the height of each cell. (the line height).
Is there a better solution?
Yes there is. The people from TCPDF has taken the FPDF class and extended/improved it. They support HTML output. There you can use html for your outputs. Maybe you can use that.
$line_height = 5;
$width = 189;
$text = ("Your text goes here");
$height = (ceil(($pdf->GetStringWidth($text) / $width)) * $line_height);
$pdf->Multicell($width,$height,$text,1,1);
You can play with the values of $line_height and $width to fit with your font/margins/whatever you need to do, but the formula for height will calculate the number of lines needed and multiply that number by the height of each line.
I had the same issue and searched for awhile for a solution. Finally came to a relatively simple answer:
function GetMultiCellHeight($w, $txt, $pdf)
{
$height = 1;
$strlen = strlen($txt);
$wdth = 0;
for ($i = 0; $i <= $strlen; $i++) {
$char = substr($txt, $i, 1);
$wdth += $pdf->GetStringWidth($char);
if($char == "\n"){
$height++;
$wdth = 0;
}
if($wdth >= $w){
$height++;
$wdth = 0;
}
}
return $height;
}
you can use this code to solve this problem. Here the concept is only if string size greater than your cell width then font size will reduce.
$pdf->CellFit(30,20,"This is long string message.",1,0,'C',0,'',1,0);
check this URL
how to auto adjust cell width in fpdf using php and mysql
I was looking for a sophisticated solution for a while and could not find it.
I ended up just playing with the cell's width and height.
I discovered hat FPDF will play with the available space and based on that space it decides how much space goes in between lines.
So, considering the maximum possible amount of characters in my string, I could figure out how much space would be in between lines.
It works
I trying to create a custom table using FPDF Cell/MultiCell.
My 1st cell is a MultiCell that has two lines of text. The next cell should then just be placed right next to it.
Problem : no matter what I do to the next cell, it is always on the next line of the page instead of being placed right next to the 1st cell - and it's driving me crazy.
Here is my code:
require_once 'config.php';
require 'fpdf.php';
$pdf = new FPDF();
$pdf->AddPage();
$pdf->SetFont('Arial','',10);
$pdf->MultiCell(150,10,'Certificate of foreign Currency usage in respect of materials and components in terms of the notes to rebate item ',1);
$pdf->SetFont('Arial','',10);
$pdf->MultiCell(40,10,'DA190',1);
$pdf->Output();
The cell containing the text "DA190" should be placed next to the previous cell, but is being positioned underneath the previous cell.
Before printing your first multicell, record the cursor position:
$x=$this->GetX();
$y=$this->GetY();
add your multicell using $this->Multicell($w,5,'Content');
Reset the cursor position to the start height (y) and the start horizontal + the width of the 1st multicell:
$this->SetXY($x+$w,$y);
Add your next multicell and repeat as necessary.
this worked for me
$pdf->multicell(120, 5, ' ' . $actividad, 0, 'l', true);
$x = $pdf->GetX();
$y = $pdf->GetY();
$pdf->SetXY($x + 120, $y);
$pdf->Cell(70, -5, ' ' . $claseActividad, '', 0, 'l', true);
result
I found the solution - fpdf has an extension (#3) focussed on using multicells.