Is it possible to get the y position of the last HTML element when rendering an HTML document to a PDF with Dompdf?
I need to insert an element after pdf rendering at the end of my document (fields for digital signature)...
EDIT :
As described in DOMPDF Github https://github.com/dompdf/dompdf/issues/1424 ,
you need to create a callback for the event 'end_frame' :
$dompdf = new Dompdf();
$dompdf->setCallbacks(
array(
'myCallbacks' => array(
'event' => 'end_frame', 'f' => function ($infos) {
$frame = $infos["frame"];
// elements positions
$GLOBALS["array_coord"][] = $frame->get_padding_box();
// last page number
$counter_frame = $frame->lookup_counter_frame('page');
$page_number = $counter_frame->counter_value('page');
}
)
)
);
and then after the rendering :
$dompdf->render();
// get the last y position in the PDF
$ligne_sign = sizeof($GLOBALS["array_coord"]) - 2;
$y = $GLOBALS["array_coord"][$ligne_sign]["y"];
Related
I'm trying with PHP to fill form fields on an existing PDF and add an image to it.
I found the FPDM library to fill the form fields:
$formInputArray = ['field1' => 'test value', 'field2' => 'second value'];
$pdf = new FPDM('orginal-file.pdf');
$pdf->getEntries($templatePDF, 'PDF');
$pdf->Load($formInputArray);
$pdf->Merge();
$pdf->Output('F', 'form-filled-file.pdf');
That works so far.
In the next step i try to add an image with the Fpdi class to the edited document:
$pdf = new Fpdi();
$pdf->setSourceFile('form-filled-file.pdf');
$pageId = $pdf->importPage(1, \setasign\Fpdi\PdfReader\PageBoundaries::MEDIA_BOX);
$pdf->addPage();
$pdf->useTemplate($pageId);
$pdf->Image('test-image.jpg', 150*0.39, 150*0.39, 100*0.39);
$pdf->Output('F', 'finished-file.pdf');
The problem is, that Fpdi is converting the template pdf structure into an new pdf structure. So all given form fields are gone.
So the question is:
How can i add an image to an existing PDF with form fields?
I also looked at the iText / PDFtk (Serverside) and the mPDF PHP library, but they are not the right one because of the GPL license.
Is there an other way or an other library to fill form fields and add an image to an PDF in PHP?
We (Setasign - also author of FPDI) offer a commercial solution for both tasks: Filling PDF forms and fill fields with images in pure PHP.
If you'd used FPDM you was only able to fill in text fields. A replacement would be the SetaPDF-FormFiller Lite Component. The Full version would allow you to fill in also other field types such as checkboxes or radiobutton groups.
A simple example of filling a single text field and an additional field with an image would be:
<?php
require_once('library/SetaPDF/Autoload.php');
// or if you use composer require_once('vendor/autoload.php');
// create a file writer
$writer = new SetaPDF_Core_Writer_File('image-in-form-field.pdf');
// get the main document instance
$document = SetaPDF_Core_Document::loadByFilename($filename, $writer);
// now get an instance of the form filler
$formFiller = new SetaPDF_FormFiller($document);
// Get the form fields of the document
$fields = $formFiller->getFields();
// Let's fill a field
$fields['Text Field']->setValue("Some example text.");
// Now prepare an appearance for the Logo field
// First of all let's get the annotation of the form field
$annotation = $fields['Logo']->getAnnotation();
// Remember the width and height for further calculations
$width = $annotation->getWidth();
$height = $annotation->getHeight();
// Create a form xobject to which we are going to write the image.
// This form xobject will be the resulting appearance of our form field.
$xobject = SetaPDF_Core_XObject_Form::create($document, array(0, 0, $width, $height));
// Get the canvas for this xobject
$canvas = $xobject->getCanvas();
// Let's create an image xobject
$image = SetaPDF_Core_Image::getByPath('Logo.png')->toXObject($document);
// scale image into available space and align in the center
if ($image->getHeight($width) >= $height) {
$image->draw($canvas, $width / 2 - $image->getWidth($height) / 2, 0, null, $height);
} else {
$image->draw($canvas, 0, $height / 2 - $image->getHeight($width) / 2, $width);
}
// Now add the appearance to the annotation
$annotation->setAppearance($xobject);
// Flatten all appearances to the pages content stream
$fields->flatten();
// finish the document
$document->save()->finish();
This script is a short version of this demo.
I am using TCDPF to generate barcode in invoice. Thus, when I download invoice by clicking "View Invoice" from Orders page, it should download with a barcode generated. At the moment, I am just testing a random number.
In HTMLTemplateInvoice.php, I added the following codes:
// Random number for testing
$barcodeobj = new TCPDFBarcode('1234567890123', 'C39');
// Assign to template
// All other unnecessary variables not displayed
'barcode' => base64_encode($barcodeobj->getBarcodePNG(1, 30, array(255,255,255))),
);
For testing purpose, I added the following codes in invoice.addresses.tab.tpl
<img src="data:image/png;base64,{$barcode}>">
The barcode is displayed. Unfortunately, it is dislaying as a page and it is not generated in the invoice. The invoice will not download too.
I am using Prestashop 1.7.4.2 and upgraded to PHP 7.2.
I've tried this code
$barcodeobj = new TCPDFBarcode("123456789123", 'C39');
$Barcode = $barcodeobj->getBarcodePngData(2, 40, array(0,0,0));
and then i created a new pdf :
$Barcode_pdf = new TCPDF('P', 'mm', 'A5', true, 'UTF-8', false);
$Barcode_pdf->SetMargins(7, 10.4, 8);
$Barcode_pdf->setImageScale(0.5);
$Barcode_pdf->AddPage();
$Barcode_pdf->Image('#'.$Barcode,'10','20','60' );
$Barcode_pdf->Output('Barcode.pdf', 'I')
you can attach it to email if you want but change the output type to 'S':
$Barcode_attachment = array();
$Barcode_attachment['content'] = $Barcode_pdf->Output('Barcode.pdf', 'S');
$Barcode_attachment['name'] = 'Barcode.pdf'; // getting pdf file name
$Barcode_attachment['invoice']['mime'] = 'application/pdf';
$Barcode_attachment['mime'] = 'application/pdf';
and then just add $Barcode_attachment to your email .
I am using TCPDF library to write a custom size label with background image and multiple text blocks on it.
The user when sees the preview on screen of the PDF it should show in horizontal, but for printing, I need the full page rotated -90 degrees.
How can I just rotate the whole page for printing version without having to move anything?
Basically:
In my case I've already had to use a new document format for the special sizes my document required.
So I've duplicated that format, created one for Landscape and one for Portrait.
Then based on the $preview variable, if previewing I'm rendering the normal landscape document, but if not previewing, I'm using the Portrait format and orientation and also starting the transformation and rotating everything on page.
Hope this helps someone I've found no other "quick" way to accomplish this kind of full-page rotation.
<?php
// #1 get the preview attribute from
// the form that was submitted from the user
$preview= isset($_POST['preview'])?(int)$_POST['preview']:0;
// load TCPDF for CodeIgniter as a library
$this->load->library('Pdf');
// #2 set default orientation and format
$orientation='L';
$format='MAKE-L';
// #3 if not previewing, switch orientation and format to portrait
if (!$preview) {
$orientation='P';
$format='MAKE-P';
}
// create new pdf object
// (same as doing new TCPDF(), it is just the CodeIgniter wrapper)
$pdf = new Pdf($orientation, 'mm', $format, true, 'UTF-8', false);
// remove default header/footer
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->SetMargins(0, 0, 0);
$pdf->AddPage($orientation, $format);
// #4 if not previewing, start transformation
// and rotate everything before inserting any content
if (!$preview) {
// Start Transformation
$pdf->StartTransform();
// Rotate counter-clockwise centered by (x,y)
$pdf->Rotate(-90, 70, 70); // <-- TODO: test this very well because 70 and 70 was just guessing, there is no math behind that so not sure if it will work always
}
// put your content here,
// for example set font and add a text
$pdf->SetFont('times', '', 7, '', true);
$pdf->writeHTMLCell(0, 0, 25.4, 2, 'lot number', 0, 1, 0, true, '', true);
/// end content
// #5 if not in preview mode, finish the transformation
if (!$preview) {
// Stop Transformation
$pdf->StopTransform();
}
$pdf->Output('example.pdf', 'I');
/**
* Last but very important note:
* I have added my formats in tcpdf/includes/tcpdf_static.php file.
* >> MAKE-L for Landscape
* >> MAKE-P for Portrait
*/
public static $page_formats = array(
// Make
'MAKE-L' => array( 396.850, 425.196), // = ( h 140 x w 150 ) mm
// Make
'MAKE-P' => array( 425.196, 396.850 ), // = ( h 140 x w 150 ) mm
// .. rest of formats here ../
);
The setPageFormat() method should do the job. You also can pass the parameter to the $format parameter of AddPage():
$pdf->AddPage($orientation, ['format' => $format, 'Rotate' => -90]);
I have setup OpenTBS to generate dynamically from my contacts database. Now I want to setup the actual content of the email to come from a MySQL table created using CKeditor or another WYSISYG JS editor.
I have been able to get the content to display on the outputted docx file but it is coming this as a straing with the html tags, I somehow need this to format so it comes though as it was put in by the client. I am only going to allow them to use the basics, paragrahs, bold, italics and maybe a few other tags.
Is this someway I can convert this html string to word copy / text? Or somehow have a different WYSIWYG editor to save it in MySQL as word code rather then html code.
Thanks
It's not really relevant but below is the function that generates the OpenTBS document from a template and the database (I am using CakePHP) MailMerge.description is the body with the html code at the moment.
// FUNCTION EXPORT MAIL MERGE
// -------------------------------------------------------------->
function mail_merge()
{
Configure::write('debug',2);
$this->layout = null;
$this->autoRender = FALSE;
// GET THE CONTACTS
// ------------------------------------------------------------->
$contacts = $this->Contact->find('all', array('limit' => 20, 'contain' => FALSE));
$this->loadModel('MailMerge');
$content = $this->MailMerge->find('first', array(
'conditions' => array('MailMerge.id' => 1),
'fields' => array('MailMerge.description')
));
// Get a new instance of TBS with the OpenTBS plug-in
// ------------------------------------------------------------->
$otbs = $this->Tbs->getOpenTbs();
// Load the template file
// ------------------------------------------------------------->
$otbs->LoadTemplate(APP . DS . WEBROOT_DIR . '/files/data_files/enquiry_letter_sample_redcliffe.docx');
// Merge data in the template
// ------------------------------------------------------------->
$otbs->MergeBlock('r', $contacts);
$otbs->MergeBlock('content', $content);
// End the merge and export
// ------------------------------------------------------------->
$file_name = 'export.docx';
$otbs->Show(OPENTBS_DOWNLOAD, $file_name);
}
I am using DOMPDF to generate a PDF file from PHP. It works very good.
But now when I click on the link that generates the PDF I want it to take me to the fifth page of the PDF (if there's content on that page). Is there a way to do this?
According to the source code posted on this page, you can use the function Cpdf.openHere:
/**
* specify where the document should open when it first starts
*/
function openHere($style, $a = 0, $b = 0, $c = 0) {
// this function will open the document at a specified page, in a specified style
// the values for style, and the required paramters are:
// 'XYZ' left, top, zoom
// 'Fit'
// 'FitH' top
// 'FitV' left
// 'FitR' left,bottom,right
// 'FitB'
// 'FitBH' top
// 'FitBV' left
$this->numObj++;
$this->o_destination($this->numObj, 'new', array('page' => $this->currentPage, 'type' => $style, 'p1' => $a, 'p2' => $b, 'p3' => $c));
$id = $this->catalogId;
$this->o_catalog($id, 'openHere', $this->numObj);
}