I have a problem creating tables with fpdf.
Can anyone help me making this page (or at least tell me how to do it)?
invoice tables
Or can you show how to convert HTML tables to FPDF tables and put the code here?
I also have this (along with the connection to the database):
$person = mysql_fetch_array($result);
I would like this to function when added inside the tables with this = (example)
$pdf->Cell(0,260,''.$person["CA"],'C',0 ,1); --- .$person["CA"]
Can anyone help me?
Well, FPDF works kinda like a typewriter, in that it has a roving X,Y point which it writes to, which you can manually move around or let it do it for you.
I don't know if the huge whitespace at the left is required. If so, you'd have to call $this->SetX($coordinate) before each write.
You should do something like this:
class InvoicePDF extends FPDF //Create a new class to contain the header/footer/etc. which extends FPDF
{
public function Header()
{
//Header stuff goes here, like the big Invoice
$this->SetY(10); //SetY 10 units down from the top, experiment with distance to get appropriate distance
$this->SetFont('Arial','',20); //Set Font to Arial/Helvetica 20 pt font
$this->SetTextColor(0,0,0); //Set Text Color to Black;
$this->Cell(0,9,"INVOICE",0,0,'R'); //Write the word INVOICE Right aligned in a box the width of the page, will put it at the far right of the page
}
public function Footer()
{
//any footer stuff goes here
}
public function FillHeadInfo($info) //$info would be an array of the stuff to fill the small table at the top
{
$this->SetY(0); //reset the Y to the original, since we moved it down to write INVOICE
$this->SetFont('Arial','',12);
$this->SetFillColor(224,224,224); //Set background of the cell to be that grey color
$this->Cell(20,12,"Order #",1,0,'C',true); //Write a cell 20 wide, 12 high, filled and bordered, with Order # centered inside, last argument 'true' tells it to fill the cell with the color specified
$this->Cell(20,12,"Coding",1,0,'C',true);
$this->Cell(20,12,"Sales Code",1,1,'C',true); //the 1 before the 'C' instead of 0 in previous lines tells it to move down by the height of the cell after writing this
$this->Cell(20,12,$info['ordernum'],1,0,'C');
$this->Cell(20,12,$info['coding'],1,0,'C');
$this->Cell(20,12,$info['salescode'],1,1,'C');
$this->Cell(40,12,"Name & Address",1,0,'C',true);
$this->Cell(20,12,"Date",1,1,'C',true);
$y = $this->GetY(); //Need the current Y value to reset it after the next line, as multicell automatically moves down after write
$x = $this->GetX(); // Might need the X too
$this->MultiCell(40,12,$info['customername'] . "\n" . $info['address'] . "\n" . $info['city'] . ', ' . $info['state'] . ' ' . $info['zip'],1,'L',false); //I assume the customer address info is broken up into multiple different pieces
$this->SetY($y); //Reset the write point
$this->SetX($x + 40); //Move X to $x + width of last cell
$this->Cell(20,36,date("format",strtotime($info['date'])),1,1,'C'); //Might be easier to use $this->Rect() to draw rectangles for address and date and then write the address and date into them without borders using SetX and SetY, if the borders don't line up or whatever
}
public function fillItems($items)
{
//You'd build the items list much the same way as above, using a foreach loop or whatever
//Could also easily combine this function and the one above
}
}
Then, when creating the pdf you'd do something like this:
require_once('fpdf.php');
require_once('class.invoicepdf.php');
//Get whatever info you need to fill the pdf
$pdf = new InvoicePDF('P','mm','Letter');
$pdf->AddPage();
$pdf->FillHeadInfo($info); //Could also pass $_POST and rely on the keys of the $_POST array
$pdf->FillItems($items);
$pdf->Output('filename.pdf','I');
By the way, I'd suggest rather than trying to write it from $_POST, you save the order to the DB, then pass the order ID along to the script to write the pdf via a link and $_GET, and have the script retrieve the info from the DB, this way you can select only the info you need.
Related
I have dynamic data. So my data can change
besides that I also have a data signature that cannot be separated.
This signature data must be on the same page. See the red mark in this image :
It is a unit and cannot be separated. Signature data
must be on the same page
My problem is because my data is dynamic. This makes the position of the signature data can be located in any position. See image below :
Because my data increases, the position of the headmaster in the signature data is separate
How do I make signature data (see picture 1), which red marks automatically move to the next page if the data is separate?
You can set manual page breaks with something like this:
<?php
//All lines are written from the sheet code at this moment
//The code will insert a page break and the repeated header
//Page margins
$sheet->getPageMargins()->setTop(0.5);
$sheet->getPageMargins()->setRight(0.75);
$sheet->getPageMargins()->setLeft(0.75);
$sheet->getPageMargins()->setBottom(1);
//Use fit to page for the horizontal direction
$sheet->getPageSetup()->setFitToWidth(1);
$sheet->getPageSetup()->setFitToHeight(0);
$headerItems = array(); //add your header items here as array
$headerRowsHeight = 0;// calculated height of header and images of the top
$rowCounter = 100; //get last written row
//add (other) modifier of page hight here
$pageHeight=25+50 + $headerRowsHeight; //Current used page height Header + Footer + $headerRowsHeight
$reset = $pageHeight; //If you will have the firstpage diffrent change reset value and/or pageheight
$pageMaxHeight = 980 ; //Maximale page height DIN A4 arround this
$pageClearance = 15; //Clearance of footer
//Iterate trough all written lines
for ($row = 1; $row <= $rowCounter; ++$row) {
$height=15.1; //standard row height
//get the row height
$dim = $sheet->getRowDimension($row)->getRowHeight();
//get special cell heights (non standard)
if($dim != -1){
$height=$dim;
}
//add height for line to pageheight = get current used space
$pageHeight = $pageHeight + $height;
//Check if the space is still in the range of page
$leftOverSpace = $pageMaxHeight-$pageHeight;
//Change $pageClearance to your preferd space before footer
if( $leftOverSpace < $pageClearance){
//Set pagebraek
$sheet->setBreak('A'.$row, \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet::BREAK_ROW);
//Reset page height
$pageHeight=$reset;
//Add page header to new page
createHeader($sheet, $row+1, $headeritems);
}
}
//Creates a header for every page
function createHeader($sheet, $row, $texts){
$count = $row;
// Iterate trough the header text array
foreach($texts as $text){
//Insert a new line with header
$sheet->insertNewRowBefore($count, 1);
//Do your header stuff here
$count++;
}
//Add two lines after the header
$sheet->insertNewRowBefore($count, 2);
//Return row number
return $count;
}
?>
Place not that the calculation is not 100% exact and that you must adapt this to your code.
I have some records stored on a database. I would like to print them onto some Avery labels. I can use FPDF to create a pdf document. I can use PDF_Label which extends FPDF to easily position the information to align with Avery labels. So far so good.
In addition to outputting text, I would like to represent some of the data in a qr code. I can create the qr codes, storing them temporarily on disk as .png files. I can insert the qr_codes as images into a .pdf document. So far so good.
But here is the problem: PDF_label creates 'cells' which align with Avery labels and specifically handles text, not images. How can I 'easily' insert each qr code into each label?
I have looked online for two days but there seems very little guidance on this - other than one piece of advice that sepcicially warns NOT to insert images into FPDF Cells.
One option perhaps would be to use TCPDF but I would appreciate some recommendations on what extension if any would be useful.
For the record, my code so far is:
<?php
require_once( 'vendor/fpdf181/fpdf.php' );
require_once( 'vendor/fpdf_label/PDF_Label.php');
require_once( 'vendor/phpqrcode/qrlib.php' );
// fetch data from database
/* … works fine and creates an array of locations … */
foreach( $locations as $location )
{
$title = "Location " . $location['id'];
$name = $location['name'];
$footer = "https://www.example.com/something/";
$barcode_text = "https://www.example.com/something/?t=1&u=1&l=" . $location['id'];
// create a temporary file to hold the barcode.png
$filePath = './qr_codes/temp_'. $location['id'] . '.png';
$qr_code = new QRcode();
QRcode::png( $barcode_text, $filePath );
$text = "";
$text .= sprintf( $title . "\n" . $name . "\n");
$text .= $pdf->Image( $filePath, $pdf->GetX(), $pdf->GetY(), 20 );
$text .= sprintf( "\n" . $footer );
//$pdf->Add_Label($text);
$pdf->Add_Label($text);
}
From 7 records, this generates just 3 qrcodes on the pdf. Possibly several images overlay one another. The qr_codes are vertically aligned for the top of each row of labels but not correctly positioned horizontally. Presumably this is because that is the position given by GetX and GetY at the time those methods are called.
Any help much appreciated ...
Solved with help to the response to this question:
How can I use TCPDF to make 2x6 sheets of labels that include 2D barcodes WITHOUT using columns OR 3rd-party classes?
I used TCPDF and the recommended method of creating the qrcode and then a cell 'around' it to print out text
I'm using PHPExcel to convert Excel file into HTML table.
Since I've added this Jquery function to fix my first top row (because Phpexcel doesn't generate <thead></thead> tags :
I'm using http://mkoryak.github.io/floatThead/ plugin Jquery..
var table = $('#sheet0'); // select the table of interest
var thead = $('<thead/>').prependTo(table); // create <thead></thead>
table.find('tbody tr').eq(0).appendTo(thead);
// Now the table is ready to have your chosen method applied to fix the position of the thead.
$('table#sheet0').floatThead({
position: 'fixed',
index: '8',
overflow: 'auto'
});
I just want to load the first 13 columns, I made a ReadFilter but it doesn't work properly..
Here you can see the code which loops through the cells :
https://github.com/PHPOffice/PHPExcel/blob/master/Classes/PHPExcel/Writer/HTML.php#L356
How can I stop the loop at the 13'th column ?
You'd have to modify the Writer code to limit it, that functionality isn't built into PHPExcel; unless you prevented it reading those extra columns with a read filter
To show only 13 columns i did that in Writer/HTML.php :
public function generateSheetData() {
// CODE HERE
// Get worksheet dimension
$dimension = explode(':', $sheet->calculateWorksheetDimension());
$dimension[0] = PHPExcel_Cell::coordinateFromString($dimension[0]);
$dimension[0][0] = PHPExcel_Cell::columnIndexFromString($dimension[0][0]) - 1;
$dimension[1] = PHPExcel_Cell::coordinateFromString($dimension[1]);
** HERE **
$dimension[1][0] = 13;
it works great , not blank cells !
Since i use "floatThead plugin" like above in my post, blank cells appears only in the :
HTML Output :
How can i access this th.floatThead to remove() him ?
Something like that Jquery ? :
table.find('thead th.floatThead-col:nth-child(8)').remove();
Unable to access th.floatThead-col to remove it..
I'm trying to generate a table in fpdf with dynamic content in it. The problem is in the line $pdf->MultiCell(50,10,$d2['shade'],'LRB',1);. This cell has a lot of
content in it. So when the height of this cell is increased, the height of other cells remains the same. How do I adjust it accordingly?
$sql3 = "SELECT `materialDesc`,`chart`,`materialSize`,`remarks`, GROUP_CONCAT(shade SEPARATOR ',')shade, GROUP_CONCAT(shade SEPARATOR ',')shade SUM(quantity)quantity FROM `" . $DB->pre . "order_detail` WHERE `orderID`= '$orderID' GROUP BY `materialSize`, `materialDesc`,`chart`,`remarks` ";
$rows3 = $DB->dbRows($sql3);
if ($DB->numRows > 0){
$pdf->SetLineWidth(0);
$pdf->SetFont('Arial','',10);
$newL=90; ////fixed cell spaced in y-axis for quantity
foreach ($rows3 as $d2) {
$pdf->SetXY(11,$newL);
$pdf->MultiCell(30,10,$d2['materialDesc'],'LRB',1);
$pdf->SetXY(41,$newL);
$pdf->MultiCell(13,10,$d2['chart'],'LRB',1);
$pdf->SetXY(54,$newL);
$pdf->MultiCell(50,10,$d2['shade'],'LRB',1); /////line with the problem/////
$pdf->SetXY(104,$newL);
$pdf->MultiCell(13,10,$d2['materialSize'],'LRB',1);
$pdf->SetXY(117,$newL);
$pdf->MultiCell(12,10,$d2['quantity'],'LRB',1);
$pdf->SetXY(129,$newL);
$pdf->MultiCell(15,10,'ROL','LRB',1);
$pdf->SetXY(144,$newL);
$pdf->MultiCell(18,10,'OPEN','LRB',1);
$pdf->SetXY(162,$newL);
$pdf->MultiCell(35,10,$d2['remarks'],'LRB',1);
$newL += 7;
}
}
$pdf-> Ln();
You can find the NbLines() method in this script, which allows you to pre-calculated the needed lines of a multicell.
With this information you can use MultiCell throughout but you have to draw the borders your own (as you also can see in the link above).
I have seen quite a few questions on this but not definitive answer. Im using FPDF to dynamically create PDF with values form a DB, I only want a footer on the last page, seeing as its values are based on DB values the PDF could be 2,3,4 pages long. So i started messing around with the footter of FPDF like so
function Footer()
{
$this->SetY(-15);
$this->SetFont('Arial','I',8);
//Page number
$pagenumber = '{nb}';
if($this->PageNo() == 2){
$this->Cell(173,10, ' FOOTER TEST - '.$pagenumber, 0, 0);
}
}
This retruns the value "FOOTER TEST - 2" on the second page and if i set the if to "<=2" will put the same on page one and two, GREAT! it recognises $pagenumber as 2 or if i had 3 pages as 3, so it can see that i have however many pages, however, when i change the code to:
function Footer()
{
$this->SetY(-15);
$this->SetFont('Arial','I',8);
//Page number
$pagenumber = '{nb}';
if($this->PageNo() == $pagenumber){
$this->Cell(173,10, ' FOOTER TEST - '.$pagenumber, 0, 0);
}
}
Thinking that it output the last page once, adding that to the if statement will make it work, it doesn't display anything, like the if statement cant recognize the value for $pagenumber, is this because it is a string or int trying to compare to the opposite or something else?
Any help greatly appropriated.
Ian
{nb} is done as a late replacement after you have finished writing (as it doesn't know how many pages there are before that) whereas the footer is output whenever a page is complete, your best bet is to probably set a flag on the class to true when you have finished outputting everything and then check the flag in the footer
function Footer()
{
$this->SetY(-15);
$this->SetFont('Arial','I',8);
//Page number
if($this->isFinished){
$this->Cell(173,10, ' FOOTER TEST - {nb}', 0, 0);
}
}
and then in your PDF writing code
...
$pdf->isFinished = true;
Hope this helps
I'm late to the party too - LOL Paul is on the right track. I amended his solution to work with a while loop.
$pdf = new PDF();
$pdf->isFinished = false;
$pdf->AddPage();
// Add your page contents here
while($row1 = $rs1->fetch_assoc()){
// output...
$pdf->isFinished = false;
}
$pdf->isFinished = true;
Now In the Footer...
function Footer()
{
$this->SetY(-15);
if($this->isFinished){
$this->Cell(195,10, "Signature:_______________________________", 0, 0,'R');
}
}
I hope this helps someone.
If you use MultiCell() and AutoPageBreak, the content you're writing may create an automatic page break.
In this case, setting a boolean flag before a MultiCell() call can create the last footer expected on the last two pages instead of the very last one only.
At the end of your code, when you don't have anything else to write in your document, do the following :
$this->InFooter = true;
$this->SetY(-15);
$this->Write(5, "My end footer text");
$this->InFooter = false;
InFooter boolean tells to FPDF that we are writing content in the Footer and FPDF will not automatically create a page break.
SetY() is needed otherwise your content will be written outside the document.
I know i'm a little late to the party here but when I ran into this same problem it was because I was not calling the AliasNbPages() function. The example they give doesn't seem to include this in their code !
I just call it right after I make a new pdf:
$pdf = new PDF();
$pdf->AliasNbPages();
Now my {nb} is replaced with the total number of pages !
For people stumbling upon this question many years later: Danny's answer above can also be used to skip the footer (or header) on any arbitrary page. You just need to make sure that you set your skip-Boolean to true after adding the page, then add the content, and set it back to false in case you want a footer on the next pages.
$pdf = new PDF();
$pdf->isFinished = false;
// [...]
$pdf->AddPage();
$pdf->isFinished = true;
// Add your page contents here
$pdf->isFinished = false;
I posted a longer version here.
I would have liked to add this as a comment to Danny's answer. However, being new and low on reputation, I had to post my own. :/
Your Main class:
$o_pdf->AddPage(); //need to add first and set isFinished true
$o_pdf->isFinished = true;
And your FPDF extended class:
if($this->isFinished) {
//your footer on last page
}
Hope this will be useful for you!!!