Add a page before first page in TCPDF - php

I have a HTML document which I'm converting to PDF using TCPDF. The HTML document contains several html tables. This works fine. But, I also need to add the number of pages in the PDF doc to the first page. Is there any solution to build the PDF file and then add a page before current first page ?

I don't know if it works with HTML, but I found a solution that worked for me with movePage.
You create the page, get its position and move it to the first position :
$pdf->AddPage();
$pdf->Cell(0, 10, 'My content');
// Get the current page number
$pageNo = $pdf->PageNo();
// First page of the document
$toPage = 1;
$pdf->movePage($pageNo, $toPage);
Official example here : https://tcpdf.org/examples/example_044/

You should be able to calculate how many pages there will be based on the size of your tables. I would read in all the html data, measure it, and then start to make the PDF.

The idea I found is to clone the TCPDF instance and get the returned number of pages:
$tmp_pdf = clone $pdf;
$tmp_pdf->AddPage();
$tmp_pdf->writeHTML($report, true, false, true, false, '');
$num_pages = $tmp_pdf->getNumPages();
unset($tmp_pdf);
$report = preg_replace('#\{num_pages\}#is', $num_pages, $report);

Related

pdf file output created with FPDF are empty (PHP)

Hi and thanks by advance for you helps.
I'm trying to write on a PDF with FPDF on PHP.
I'm actually working on WordPress.
If I'm using this code on my first website, it's working well:
if (isset($_GET["obtenir-mon-analyse"])){
$pdfFile = getcwd() . '/wp-content/themes/childtheme/ressources/PDF_analyse_template.pdf';
require_once('library/fpdf/fpdf.php');
require_once('library/fdpi/src/autoload.php');
// initiate FPDI
$pdf = new setasign\Fpdi\Fpdi();
// add a page
$pdf->AddPage("L");
// set the source file
$pdf->setSourceFile($pdfFile);
// import page 1
$tplIdx = $pdf->importPage(1);
// use the imported page and place it at point 10,10 with a width of 100 mm
$pdf->useTemplate($tplIdx, 0,0 );
$pdf->Output('I');
}
But, with the same code on another website, the PDF generated by the output function is empty (0kb).
Also, the template is working because FDPF is well detecting the available page number.
PS:
The 2 website are hosting on the same host.
I have not any error.
I really don't know where is the problem.
Thanks a lot.
I think nobody will see this answer but:
On wordpress
With the plugin WP-optimize
If you use the mimify option on HTML, you will not be able to use FPDF

How to bulk generate PDF from HTML templates ready for double-sided printing in PHP?

I've been struggling with this for a while and feel helpless.
Prestashop uses tcpdf to generate invoices and delivery slips from HTML templates filled using Smarty. We are working on updating the invoice design and found tcpdf to be lacking in CSS support. After some research we settled for wkhtmltopdf as the right tool from converting the HTML/CSS templates to PDF.
The problem
The store has a feature for exporting multiple invoices into a single PDF. Using TCPDF I was able to make the batch file ready for double sided printing by inserting a blank page after each invoice that had odd number of pages before the file was generated. But now that we switched to wkhtmltopdf I cannot achieve the same result.
The crucial problem is that while wkhtmltopdf allows for the usage of multiple HTML templates there seems to be no reliable way to determine the number of pages they are each going to have before the file is generated. The header and footer templates can receive the page count that the invoice ends up being but they are separate from the main content and therefore I cannot insert a page break accordingly.
I've also tried to calculate the height of the content / PDF page height but there were various issues with that once I started exporting multiple templates (worked alright with a single template). This approach isn't great either because inserting a blank page into the content itself causes the footer to appear on the new page as well which is not what I want.
My best attempt
The only way I've figured out that could get me around these issues is very inefficient. Each time a template is added to the batch I could pre-generate it using a separate instance of a wrapper for wkhtmltopdf, get the temporary file name, determine how many pages it has using pdfinfo and add a blank HTML template to the main instance accordingly. Here's a draft of a function to get the number of pages of the last template added (from a class that extends the wrapper, based on some other pdfinfo questions I found on SO):
/**
* Return the number of pages in the last invoice template added
* $complete === true => return the length of the entire document
*/
public function getNumPages($complete = false)
{
if (!$complete) {
// Generate PDF of last template added
$tmpPdf = new WKPdf($this->_options);
$tmpPdf->addPage($this->content, Array(
'footer-html' => $this->footer
));
/**
The createPdf method is protected so I need to get
the content as string here to force the wrapper to
call wkhtmltopdf.
*/
$tmpPdf->toString();
$document = $tmpPdf->getPdfFilename();
} else {
// Generate entire batch
$this->createPdf();
$document = $this->getPdfFilename();
}
// Use pdfinfo to get the PDF page count
$cmd = 'pdfinfo';
exec("$cmd \"$document\"", $output);
$pagecount = 0;
foreach($output as $op)
{
// Extract the number
if(preg_match("/Pages:\s*(\d+)/i", $op, $matches) === 1)
{
$pagecount = intval($matches[1]);
break;
}
}
return $pagecount;
}
This is very inefficient - it takes about 80 seconds to generate a batch of 25 invoices because I have to call wkhtmltopdf 25 times to create the temporary PDF files so that I can call pdfinfo 25 times to get their individual lengths and insert blank pages where necessary and then generate the final document.
The advantage of TCPDF is that it can give you the number of pages on the fly and a similar functionality takes about 5 seconds to generate a batch file of 25 invoices.
Anyone has any ideas on how to speed things up? Or a better idea to do this altogether. I've considered various tools for the generation including dompdf but wkhtmltopdf is simply the most powerful. The batch generation is really only used from the back office by the store admins so maybe they could be patient. But still.
Unfortunately wkhtmltopdf is the library, which is written in C language and we can not dynamically add one page on the fly like in PHP libraries.
Citate from your comment: Due to number of items ordered or ammount of customer data each invoice can be anywhere from 1 to 3 pages long.
And because of this we can not precalculate the number of pages and write it to a database.
I think you have only one possibility / solution: you have to write behind each invoice a blank page and after the whole PDF was generated you have to edit it with free PHP library like FPDI. In combination with FPDI it is even possible to edit PDF documents.
By PDF editing you could delete all blank pages which you do not need if they starts with odd page number (like 3, 5, etc.). And in FPDI you have the possibility to detect a page number. It is much faster than the solution which you use now.
And the blank(or empty) pages you could detect on content length with FPFI like follows:
<?php
require('fpdf.php');
require_once('setasign/Fpdi/autoload.php');
class Pdf extends \setasign\Fpdi\Fpdi
{
private $pdfReader;
function Header()
{
if(is_null($this->pdfReader))
{
$readerId = $this->getPdfReaderId('blank-pages.pdf');
$this->pdfReader = $this->getPdfReader($readerId);
}
$page_fpdi = $this->pdfReader->getPage($this->PageNo());
$this->content = $page_fpdi->getContentStream();
$this->Cell(0, 15, 'page content length: '.strlen($this->content));
}
protected function _putimages(){}
}
$pdf = new Pdf();
$pdf->SetFont('Arial', '', 12);
$pdf->AddPage(); //page content length: 70 // page with 'Hello World!' string
$pdf->AddPage(); //page content length: 30 // empty page
$pdf->AddPage(); //page content length: 30 // empty page
$pdf->Output();
?>
My blank-pages.pdf I have generated using FPDF with following code:
<?php
require('fpdf.php');
$pdf = new FPDF();
$pdf->AddPage();
$pdf->SetFont('Arial','B',16);
$pdf->Cell(40,10,'Hello World!');
$pdf->AddPage();
$pdf->AddPage();
$pdf->Output();
?>

mPDF very heavy file after import one page from external pdf

I import external pdf file and try tuuse only first page of it but weight of new pdf is as heavy as full pdf , and is only containing first page when external file contain like 200 pages .
Any idea why , or is maybe some sort of clear command to drop rest of pages from memory of new pdf ??
my code is very simple:
$pdfp = new mPDF('utf-8','A4-L');
$pdfp->displayDefaultOrientation = true;
$pdfp->SetImportUse();
$pagecount = $pdfp->SetSourceFile('ORGINAL.PDF');
///// first page only
$import_page = $pdfp->ImportPage(1);
$pdfp->UseTemplate($import_page);
$pdfp->Output('firstpageonly.pdf', 'F');
any idea , please :)
Regards
Hubert

How to split a pdf doc vertically and display the pages in order

I have a pdf doc which has 2 pages per page I want to split the page vertically and display the page in order (eg 100 page pfd doc will get converted to 200 pages doc)
I want to code it in may be php/javascript (is it possible). I want to upload any pdf doc to my website and then split it vertically then display the pages in order
Please let me how how to do this, I have tried to google but I could not find a solution
thanks
Edit:
I am trying to use clipRectangel() method:
<?php
require_once 'Zend/Pdf.php';
$pdf = Zend_Pdf::load('pages.pdf');
$page = $pdf->pages[0];
$page->clipRectangle(10, 10, 30, 30);
$pdf->save('new.pdf');
?>
I am trying to use clipRectangle to split vertically but I am not getting any modified pdf in 'new.pdf' I also want to order the pages,please suggest any better way to use zend. It would be helpful if you can give me few lines of code.
This is a pretty tall order.
Your best bet is to use Zend_Pdf which allows loading and altering of (unprotected) PDF files in php. Javascript cannot do this.
This is of course not something that will work with just any PDF in any circumstance. You can get cut off text (half on one page, half on the other) as the entire process is not like HTML text.
Converting a PDF to HTML is a whole other thing.
Update: I've taken your code simply for illustration. Haven't tested this, but if you get errors, you should be able to find the solution rather quickly.
require_once 'Zend/Pdf.php';
$pdf = Zend_Pdf::load('pages.pdf');
$pdfnew = new Zend_Pdf();
foreach ($pdf->pages as $page) {
$curpage = $page;
// Clipping for first part, enter your own numbers..
$curpage->clipRectangle(10, 10, 30, 30);
$pdfnew->pages[] = $curpage;
$curpage = $page;
// Clipping for second part, enter your own numbers..
$curpage->clipRectangle(10, 10, 30, 30);
$pdfnew->pages[] = $curpage;
}
$pdfnew->save('new.pdf');

How to get a page count in an mPDF document?

Does anybody knows how to get the number of generated pages if a PDF document using mPDF library?
I was looking for the same functionallity while using EYiiPdf (a wrapper for mPDF on Yii) and the following worked like a charm:
$mPDF->setFooter('{PAGENO} / {nb}');
I checked mPDF's source and found this at mpdf.php:1656 (version 5.4):
function AliasNbPages($alias='{nb}') {
//Define an alias for total number of pages
$this->aliasNbPg=$alias;
}
Hope it helps!
You can use {nbpg}, like
<div align="center"><b>{PAGENO} / {nbpg}</b></div>
If you are trying to return the number of pages so you can save this to a database or some other operation outside of mpdf it's easy to pull it this way.
After you write your content:
$mpdf->WriteHTML($html);
$page_count = $mpdf -> page;
$mpdf->Output();
add this to a main mPDF class:
function getPageCount() {
return count($this->pages);
}
then add a html-parser such string:
$html = str_replace('{PAGECNT}', $this->getPageCount(), $html);
after these actions you can insert {PAGECNT} directly in your parsed HTML to get the result. This is useful is you need to indicate a page:
replacement aliases {nb} and {nbpg} for total number
{PAGENO} for current page number
UPDATE
Please note, this answer refers to mdf library v4, which was a current version at the time of writing.
Minimum Working Example by #aiao
<?php
$pagenumber= '<!--mpdf Page {PAGENO} of {nbpg}mpdf--> $mpdf->WriteHTML($pagenumber);
$mpdf->Output();
?>
<?php
$pagenumber= '<!--mpdf Page {PAGENO} of {nbpg}mpdf--> $mpdf->WriteHTML($pagenumber);
$mpdf->Output();
?>
Watch for the line:
preg_replace('/\{DATE\s+(.*?)\}/e',"date('\\1')",$hd);
in mpdf.php function Footer()
It may cause your "{PAGENO} / {nb}" to not be displayed.
Just comment it out or use strpos('{DATE' > -1) to check if it is available.
Also you may need to add:
$mpdf->ignore_invalid_utf8 = true;
and also if you don't want footer line:
$mpdf->defaultfooterline = false;
After these changes the pagination worked for me at last.

Categories