I've created a form that allows users to create a pdf that has an unlimited number of pages, I've got SetAutoPageBreak set so that it continues onto a second page however I cannot get the pages created after the page break to continue to use the original template file. The basic code can be seen below.
require('fpdf.php');
require('fpdi.php');
$pdf = new FPDI('P','mm','A4');
$pageCount = $pdf->setSourceFile("source_file.pdf");
$tplIdx = $pdf->importPage(1);
$pdf->AddPage();
$pdf->useTemplate($tplIdx);
$pdf->SetTextColor(63,76,89);
$pdf->SetMargins(5,39,5,20);
$pdf->SetAutoPageBreak(true,22); //page created doesn't have template attached
$pdf->SetDrawColor(225,225,225);
$pdf->SetFillColor(248,248,248);
$pdf->SetLineWidth(1);
$pdf->SetXY(82, 40);
$pdf->MultiCell(165,5,$company.$block,0,L,false);
$pdf->SetXY(19, 45);
$pdf->MultiCell(165,5,$date.$block,0,L,false);
$pdf->Output();
Having looked around, this question is the closest I can find however I'm not sure whether it is even relevant: FPDF/FPDI UseTemplate
Thanks
Just place the imported page in the Header method:
class PDF extends FPDI
{
protected $_tplIdx;
public function Header()
{
if (null === $this->_tplIdx) {
$this->_tplIdx = $this->importPage(1);
}
$this->useTemplate($this->_tplIdx);
}
}
$pdf = new PDF('P','mm','A4');
$pdf->AddPage();
...
...and everything should work as expected.
in addition to #JanSlabon`s answer: (i dont have the needed reputation to write a comment, so i´ll post this here, hope that´s ok)
If you only want to use a certain template for the first page and a different one for all other pages, you can do so as follows:
class PDF extends FPDI
{
protected $_tplIdx;
public function Header()
{
if (null === $this->_tplIdx) {
$this->setSourceFile('paper1.pdf');
$this->_tplIdx = $this->importPage(1);
} else {
$this->setSourceFile('paper2.pdf');
$this->_tplIdx = $this->importPage(1);
}
$this->useTemplate($this->_tplIdx);
}
}
i know its not exactly what #Searlee was looking for, but maybe it helps someone else.
Related
I have lot of code for creating pdf (TCPDF) separate by header, body, footer...
and I need to call the code as needed with variable coordinates. Because I need use if else calls are (of course) multiple and needlessly I rewrite the same code.
For example I try this (subheader):
class invoice {
function getSubheader($disY){
$subheader = array(
$pdf->SetLineWidth(.2),
$pdf->MultiCell(190,9,'',1,'L',false,0,10,$disY,true),
$pdf->SetFont('freesans','',7),
$pdf->MultiCell(50,"",$getDesc['blabla1'],0,'L',false,0,12,$disY+2,true),
$pdf->MultiCell(15,"",$getDesc['blabla2'],0,'R',false,0,62,$disY+2,true),
$pdf->MultiCell(20,"",$getDesc['blabla3'],0,'R',false,0,77,$disY+2,true),
$pdf->MultiCell(15,"",$getDesc['blabla4'],0,'R',false,0,97,$disY+2,true),
$pdf->MultiCell(25,"",$getDesc['blabla5'],0,'R',false,0,112,$disY+2,true),
$pdf->MultiCell(15,"",$getDesc['blabla6'],0,'R',false,0,137,$disY+2,true),
$pdf->MultiCell(20,"",$getDesc['blabla7'],0,'R',false,0,152,$disY+2,true),
$pdf->MultiCell(25,"",$getDesc['blabla8'],0,'R',false,0,172,$disY+2,true),
$pdf->SetFont('freesans','B',8),
$pdf->MultiCell(180,"",$getDesc['blabla9'],0,'L',false,0,12,$disY+11,true)
);
return $subheader;
}
others functions...
}
In another class call only a function
$pdf = new TCPDF (PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
$pdf->AddPage();
lot of code $pdf->...
$invoice = new invoice();
if(cond == 1){
$disY = 100;
$invoice->getSubheader($disY);
} else {
$disY = 200;
$invoice->getSubheader($disY);
}
lot of code $pdf->...
This function must return variables $pdf->SetLineWidt... etc.
But if I use this solution - error
Call to a member function SetLineWidth() on null
Any advice for a newbie?
I want to preview and download an order invoice pdf using this code :
public function generatePDFByIdOrder()
{
$order = new Order(1); //I want to download the invoice PDF of $order_id '1'
if (!Validate::isLoadedObject($order)) {
throw new PrestaShopException('Can\'t load Order object');
}
$order_invoice_collection = $order->getInvoicesCollection();
$this->generatePDF($order_invoice_collection, PDF::TEMPLATE_DELIVERY_SLIP);
}
public function generatePDF($object, $template)
{
$pdf = new PDF($object, $template, Context::getContext()->smarty);
$pdf->render();
}
And calling it with the following code :
$order = new order();
echo $order->generatePDFByIdOrder();
I have the pdf's data printed on the browser console but not downloaded .
How can I manipulate that data to download a pdf file ?
PrestaShop use TCPDF.
Edit generatePDF in this way:
public function generatePDF($object, $template)
{
$pdf = new PDF($object, $template, Context::getContext()->smarty);
$pdf->Output('name.pdf', 'I');
}
I guess you only have to set the proper headers before rendering the PDF with TCPDF like so :
header("Content-type:application/pdf");
But "downloading" a PDF will depend on what the user's browser settings. It might download them (in which case you'd have to set another header called Content-Disposition:attachment) or display it inside the browser.
We recommend you, to create a separate controller to render the PDF file and to always open that controller in a new tab. It will help you to have separate logic using DOMPDF library.
Invoice controller will be as follows (invoice.php)
include_once(_PS_MODULE_DIR_.'supercehckout/libraries/dompdf/dompdf_config.inc.php');
class SuperCheckoutInvoiceModuleFrontController extends ModuleFrontController
{
public function initContent()
{
parent::initContent();
$this->generateInvoice(ORDER_ID);
}
}
Note: SuperCheckout is the example module name.
generateInvoice() function will be as follows:
function generateInvoice($order_id)
{
$dompdf = new DOMPDF();
$html = utf8_decode(INVOICE_HTML);
$dompdf->load_html(INVOICE_HTML);
$dompdf->render();
}
I've created a PDF generator thanks to FPDF, it uses data from a mysql database and works very well. Number of pages is variable.
Then I wanted to add to every of this PDF some pages imported from other PDF files. Number of added page and adress of imported file are variable too.
It works very well, excepted that my Footer doesn't appear anymore. I want to keep this Footer on every page, the ones created by the generator and the ones imported. Can someone tell me where is the problem?..
This i my code :
require_once('gpdf/fpdf.php');
require_once('gpdf/fpdi.php');
class PDF extends FPDI
{
function Header()
{
}
function Footer()
{
// Positionnement à 1,5 cm du bas
$this->SetY(-15);
// Police Arial italique 8
$this->SetFont('Arial','I',8);
// Numéro de page
$this->Cell(0,10,'Devis from MyCompany - Page '.$this->PageNo().'/{nb}'.' Paraphes :',0,0,'C');
}
}
// Instanciation de la classe dérivée
$pdf = new FPDI();
$pdf->AliasNbPages();
$pdf->AddPage();
// Here is page 1, you don't need the details
$pdf->AddPage();
// Here is page 2, some other pages can come too
// Then begins the importation
// get the page count
$pageCount = $pdf->setSourceFile('cgua/cgu_'.$customer['num'].'.pdf');
// iterate through all pages
for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
// import a page
$templateId = $pdf->importPage($pageNo);
// get the size of the imported page
$size = $pdf->getTemplateSize($templateId);
// create a page (landscape or portrait depending on the imported page size)
if ($size['w'] > $size['h']) {
$pdf->AddPage('L', array($size['w'], $size['h']));
} else {
$pdf->AddPage('P', array($size['w'], $size['h']));
}
// use the imported page
$pdf->useTemplate($templateId);
}
$pdf->Output('devis.pdf','I');
I've found no explanation about how to keep my Footer in FPDI's manual... I'm sure it's easy to rule the problem, I just didn't find the way!
Thanks!
You created a new class that inherits the FPDI class. This new class, PDF, defines the Footer method correctly. But then you instantiated the FPDI class, instead of the PDF class.
Just change
$pdf = new FPDI();
to
$pdf = new PDF();
so that you can instantiate your new class and see the results of the new Footer method.
I have created a pdf file with FPDF in PHP. When i insert the header and footers in it, they automatically gets displayed on all the pages of the pdf file. But i want to stop these header and footer from getting displayed on the first page and display them starting from the second page of the pdf file. I have searched the net but unable to find a solution.
In other words i want to dynamically create a cover page for the pdf report i have created with FPDF.
Can anybody give me some tips on how to perform this task of hidinh header and footer from the first page in pdf file!
Any help will be appreciated!
That's an easy task. Try the following:
class PDF extends FPDF {
...
function Header() {
if ( $this->PageNo() !== 1 ) {
// Add your stuff here
}
}
function Footer() {
if ( $this->PageNo() !== 1 ) {
// Add your stuff here
}
}
}
The problem is the Footers are created in Close() method at line 288 which is called from Output() at line 987 what means you're effectively turning the Footer off and then on just to display it anyways. What I would do if I needed the flexibility is something like:
class PDF extends FPDF {
function Header() {
if (!isset($this->header[$this->page]) || !$this->header[$this->page]) {
// ...
}
}
function Footer() {
if (!isset($this->footer[$this->page]) || !$this->footer[$this->page]) {
// ...
}
}
}
and then use it like:
$pdf->header[1] = false;
$pdf->footer[1] = false;
$pdf->AddPage();
$pdf->header[2] = true;
$pdf->footer[2] = true;
$pdf->AddPage();
It might be not the most elegant solution, but it works and it effectively allows you to change the visibility of the footers dynamically (p.s.: not specifying the state would also leave you with headers on effectively reducing the amount of code you need)
I'd like to add an answer for people coming here that don't want to skip the first, but the last (or any) page. Especially handy if you have dynamically changing text and cant foresee page numbers.
This can be done by setting a boolean while adding the page to the PDF.
Define your Header / Footer as
class PDF extends FPDF {
function Header() {
if (!$this->skipHeader) {
// ...
}
}
function Footer() {
if (!$this->skipFooter) {
// ...
}
}
}
Then, when initializing the pdf make sure to set these bools to false, so you will get headers/footers in general.
$pdf = new PDF();
$pdf->skipHeader = false;
$pdf->skipFooter = false;
Once you actually want to skip a Header or Footer, set the respective bool to true
$pdf->AddPage();
$pdf->skipHeader = true;
$pdf->AddPageContents();
Remember to set them back to false if you want headers/footers on the next page!
As an extension of what Paul's said, the footer is rendered after any content, so set skipFooter to true after rendering content.
$pdf->AddPage();
$pdf->skipHeader = true;
$pdf->AddPageContents();
$pdf->skipFooter = true;
I am using TCPDF to generate PDFs. The PDF uses a PDF-template via the fpdi-class. Some of the generated PDFs are onepaged. But sometimes I have a second page. I use $pdf->MultiCell to output my content. The page-break works fine via $pdf->SetAutoPageBreak(true).
Now my problem: I need a different top-margin on the second page. What I tried so far is the use of the AcceptPageBreak()-function - unfortunaly with no success.
With the following code-snipped I managed to change the margin on the second page. But it adds one empty page at the end of the PDF.
public function AcceptPageBreak() {
$this->SetMargins(24, 65, 24, true);
$this->AddPage();
return false;
}
I tried to remove the last page with $pdf->deletePage but it does not work.
I tried to insert some conditions into the function:
public function AcceptPageBreak() {
if (1 == $this->PageNo()) {
$this->SetMargins(24, 65, 24, true);
$this->AddPage();
return false;
} else {
return false;
}
}
This works fine for PDFs with text for 2 pages. But now I get allways two paged PDFs - even if I have just a small text. It seems that the function "AcceptPageBreak()" is called every time the PDF is generated.
How can I prevent the empty page at the end of my PDF?
Using some of your code and the original function, I found out a way where it doesn't add an unneccessary blank page at the end of the file.
public function AcceptPageBreak() {
if (1 == $this->PageNo()) {
$this->SetMargins($left_margin, $top_margin, $right_margin, true);
}
if ($this->num_columns > 1) {
// multi column mode
if ($this->current_column < ($this->num_columns - 1)) {
// go to next column
$this->selectColumn($this->current_column + 1);
} elseif ($this->AutoPageBreak) {
// add a new page
$this->AddPage();
// set first column
$this->selectColumn(0);
}
// avoid page breaking from checkPageBreak()
return false;
}
return $this->AutoPageBreak;
}
I finally found a solution to my own question.
Maybe it's interesting for someone else with the same problem.
I took the function AcceptPageBreak() like posted above (Version 1). After saving the PDF I import the PDF into a new PDF without the last page and save the new PDF.
Here the code:
$pdf = new MYPDF();
$pdf->SetMargins(24, 54);
$pdf->AddPage();
...
$pdf->MultiCell('0', '', $text, '', 'L');
$pdf->lastPage();
$lastPage = $pdf->PageNo() + 1;
$pdf->Output($filePath, 'F');
// remove last page
$finalPdf = new FPDI();
$finalPdf->setSourceFile($filePath);
for ($i=1; $i < $lastPage; $i++) {
$finalPdf->AddPage();
$tplIdx = $finalPdf->importPage($i);
$finalPdf->useTemplate($tplIdx);
}
$finalPdf->Output($filePath, 'F');
Hope it helps.
TCPDF Automatic Page Breaks cause some inconsistency in rendering of content. Elements that may inadvertantly extend out of the boundaries of the page can cause additional pages to be generated. It is better to only autopage break when you are adding your content using:
$pdf->SetAutoPageBreak(true, $margin_bottom);
Then disable it when there it is not needed.
$pdf->SetAutoPageBreak(false);