fcpdf give height to cell as per text - php

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.

Related

Add one line to the cell when enter is pressed

So I just detected a problem on my fpdf, when I'm writing the description to the multicell I press enter to break line and this happens
Image with problem
but my multicell code is programmed to calculate the string size and when the size is bigger than the width of the cell it ads one break line and the height size gets bigger but when I press enter it just add the same height
example
"My name is João" -> height = 6.5
"My name is João, (line break) I'm using fpdf" -> height = 6.5 + 6.5 instead of height = 6.5 + 1
this is my pdf without pressing enter
Image
this is my pdf with multicell on action
Image
I will leave the code that it's calculating all the multicell stuff.
$size = $pdf-> h; // page size
$cellWidth=120; // width da cell
$cellHeight=6.5; // height da cell
// verificar se o texto passa a cell
if($pdf->GetStringWidth(iconv('UTF-8', 'windows-1252',$r['description'])) < $cellWidth){
//doesn't do anything because when line is multiplied it receives the same value ( 6.5 * 1 = 6.5 )
$line = 1;
}else{
$line = ceil($pdf->GetStringWidth(iconv('UTF-8', 'windows-1252',$r['description'])));
$line = round($line / $cellWidth,0) + 1;
}
// use multicell instead of cell
// as a MultiCell is always treated as end of line,
// manually set the xy position to the next cell being next.
// save a position x before writing a multicell
$xPos=$pdf->GetX();
$yPos=$pdf->GetY();
$total = $yPos + ($line * $cellHeight);
if ($total > $size - 30) { // $size = $totalheight // change page
$pdf->AddPage(); // add page
$xPos=$pdf->GetX();
$yPos=$pdf->GetY();
}
$sizecell = $pdf->GetMultiCellHeight($cellWidth, $cellHeight,iconv('UTF-8', 'windows-1252',$r['description']));
$pdf->MultiCell($cellWidth,$cellHeight,iconv('UTF-8', 'windows-1252',$r['description']),'LBR','L');
// receive the position of the cell after multicell
// equals the x with the height of the multicell
$pdf->SetXY($xPos + $cellWidth , $yPos);
// write cells
// as the variable $cellHeight is multiplied by the value of the line is going to be greater than $cellHeight
// of the multicell so we need to make a loop and subtract 0.01 until the value is the same as the multicell
$cell = $line * $cellHeight;
if ($cell > $sizecell){
while($cell > $sizecell){
$cell = $cell - 0.01;
}
} else {
$cell = $cell;
}
$pdf->Cell(15,($cell),$r['quantity'],'LBR',0);
$pdf->Cell(10,($cell),'UNI','LBR',0);
$pdf->Cell(25,($cell),$r['priceuni'].chr(128),'LBR',0);
$pdf->Cell(25,($cell),$r['sum'].chr(128),'LBR',1);
I accept any suggestions, I have no idea of how am I going to do this

fpdf multicell is not generating same height

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!

Positioning text over pdf file in PHP

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.

FPDF wrap text inside cell table

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.

Generating gradients from a hexcode or RGB in PHP/jQuery?

I'm trying to figure out how to write a function that programmatically retrieves a background-color css attribute and creates two outputs (one slightly darker than the background-color, one slightly lighter).
The idea is being able to generate a very basic linear gradient from a single color selection.
Anyone have any ideas?
To scale a color correctly, you have to multiply each RGB value by a proportion. E.g., if your color is #00417b and you want a color that is 125% lighter color then you have to do this:
var dark = {r: 0, g: 65, b: 123};
var light = {r: Math.round(Math.min(dark[r]*1.25, 255)),
g: Math.round(Math.min(dark[g]*1.25, 255)),
b: Math.round(Math.min(dark[b]*1.25, 255))};
Compare the result for yourself: dark is #00417b, and light is #00519A, although it's perfectly valid CSS to describe them as rgb(0, 65, 123) and rgb(0, 81, 154) and probably easier too. By scaling colors in this way they will appear to be at the same level of saturation, something that simply adding or subtracting numbers will not achieve.
Be aware that since values are clamped at [0, 255], if you keep shifting colors, then feeding them back into this process, you can destroy information about the proportion of red, green and blue in the source color. For this reason, keep the original color saved and try to use that as your input each time.
Since your question asked specifically about gradients though, this is how you would go between two color values:
// Suppose you have a container which is X pixels high and you want to insert a 1-pixel tall
// element at each pixel, going vertically
var min = Math.min;
var max = Math.max;
var round = Math.round;
function get_color_for_height(startColor, endColor, height, row) {
var scale = row/height;
var r = startColor[red] + scale*(endColor[red] - startColor[red]);
var b = startColor[blue] + scale*(endColor[blue] - startColor[blue]);
var g = startColor[green] + scale*(endColor[green] - startColor[green]);
return {
r: round(min(255, max(0, r))),
g: round(min(255, max(0, g))),
b: round(min(255, max(0, b)))
}
}
// some psuedo-code using an imaginary framework
for(var h = 0; h < height; h++) {
var div = new Element('div');
div.height = 1;
div.backgroundColor = get_color_for_height(start, end, height, h);
container.insert('top', div);
}
To generate a darker or lighter vairant, a simple possibility is just to add or subtract a fixed number to all three componenents, capping it at 0 and 255/0xFF.

Categories