I am developing a Java program with the following requirements:
The application will take 5 input fields and 3 images (browse and "attach" to the Java application).
Once the "form" is completed it will be submitted using a button called "submit".
Once submitted the JAVA application will create a PDF file with the 5 inputed text and the 3 attached images.
I should be able to control which goes to which page number.
How do I implement such a solution with iText?
The application will take 5 input fields and 3 images (browse and "attach" to the Java application).
Once the "form" is completed it will be submitted using a button called "submit".
These first two requirements are unclear; are they to be implemented in a Java GUI (AWT? Swing? FX?), in some independent web UI (Plain HTML? Vaadin?), or in some derived UI (Portlet? ...)?
But as the question title "Creating PDF using JAVA (Netbeans) with images and multi pages" focuses on the PDF creation, let's look at the third and fourth requirements.
Once submitted the JAVA application will create a PDF file with the 5 inputed text and the 3 attached images.
I should be able to control which goes to which page number.
Let's assume you already have those inputs in the variables
String text1, text2, text3, text4, text5;
byte[] image1, image2, image3;
The framework
With iText you now create the document like this:
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfWriter;
...
// where you want to create the PDF;
// use a FileOutputStream for creating the PDF in the file system
// use a ByteArrayOutputStream for creating the PDF in a byte[] in memory
OutputStream output = ...;
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, output);
document.open();
// Add content for the first page(s)
...
// Start e new page
document.newPage();
// Add content for the next page(s)
...
// Start a new page
document.newPage();
// etc etc
document.close();
Adding text
You can add text in one of the Add content for the ... page(s) sections using
import com.itextpdf.text.Paragraph;
...
document.add(new Paragraph(text1));
Adding an image
You can add an image in one of the Add content for the ... page(s) sections using
import com.itextpdf.text.Image;
...
document.add(Image.getInstance(image1));
Adding at a given position
Adding text or images as described above leaves the layout details to iText, and iText fills the page from top to bottom except some margins.
If you want to control the positioning of the content yourself (which also means you have to take care that the content parts do not overlap or are drawn outside the page area), you can do so like this:
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.Phrase;
...
PdfContentByte canvas = writer.getDirectContent();
Phrase phrase = new Phrase(text2);
ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, phrase, 200, 572, 0);
Image img = Image.getInstance(image2);
img.setAbsolutePosition(200, 200);
canvas.addImage(img);
And there are many more options how to manipulate your content, e.g. choosing a font, choosing text sizes, scaling images, rotating content, ..., simply have a look at the iText samples from the book iText in Action - Second Edition.
You can use XSL-FO. A basic example here. After this, you can search and add other options for your PDF.
Related
I'm using IText to generate a pdf for my project. Using help from this
How to generate a Table of Contents "TOC" with iText?, I was able to generate a pdf with TOC. However I'm unable to figure out how can I navigate to a page when page number is clicked. I tried adding action inside the pdf template but that doesn't seem to work. Thanks in advance for your help.
This is what I've added to the answer already given in the linked question:
final PdfTemplate template2 = this.tocPlaceholder.get("Test");
template2.beginText();
template2.setFontAndSize(baseFont, 12);
template2.setTextMatrix(50 - this.baseFont.getWidthPoint(String.valueOf(writer.getPageNumber()), 12), 0);
template2.showText(String.valueOf(writer.getPageNumber()));
PdfAction action = PdfAction.gotoLocalPage(writer.getPageNumber(),new PdfDestination(0),writer);
template2.setAction(action , 0,0,0,0);
template2.endText();
I have a use case that I cannot figure out how to implement.
I'm using headless chrome to export a rich text editor as a pdf and then I need to cut out a part of the created PDF and embed it as a pdf annotation in another parent pdf such that the annotation looks exactly the same as the section I cut out from the created PDF.
I'm able to correctly calculate and cut the precise area I need from the created PDF using instructions provided by:
https://developers.itextpdf.com/examples/stamping-content-existing-pdfs-itext5/cut-and-paste-content-page
PdfTemplate template2 = cb.createTemplate(pageSize.getWidth(), pageSize.getHeight());
template2.rectangle(toMove.getLeft(), toMove.getBottom(), toMove.getWidth(), toMove.getHeight());
template2.clip();
template2.newPath();
template2.addTemplate(page, 0, 0);
cb.addTemplate(template1, 0, 0);
cb.addTemplate(template2, -20, -2);
I would like to add the PDFTemplate via a PdfStamper.
Is this possible? If not now can I achieve this with another method?
In the example you refer to, you obtain cb like this:
PdfContentByte cb = writer.getDirectContent();
When using PdfStamper, you can obtain cb like this:
PdfContentByte cb = stamper.getUnderContent(p);
Or like this:
PdfContentByte cb = stamper.getOverContent(p);
The former method will add the new content under the existing content; the latter method will add the new content on top of the existing content. In these lines p is a page number (from 1 to the total number of pages of the existing document). See How to superimpose pages from existing documents into another document? for an example.
If you want to add new pages to an existing document, use the insertPage() method as explained in How to add blank pages to an existing PDF in java? Once you have added a blank page, you can add a PdfTemplate to it.
This is not a duplicate question. I had searched and tried many options before posting this question.
We have a web page, in which user should be able to input data in text boxes, text areas, images and also Rich Text editors. This data has to be filled in an existing report, like filling the blanks.
I was able to achieve the functionality using Apache FOP when the user input is simple text. But Apache FOP doesn't work if the user input is Rich Text(html format). FOP will not render html, and it just pushes the html code(ex: <strong> XYZ /strong>) into the pdf.
I tried using iText, but the setback here is that even though iText supports rendering of html to pdf, it is not able to place the images, that are included in <img> tags, in the pdf file.
I can try to create a pdf using iText api block by block, but the problem is rich text data entered by the user can not be embedded between the code since building pdf block by block and html to pdf can not be done together in iText. Or at least that is what I think from my experience.
Is there any other way to create a pdf file from java with images, rich text rendering as it is, headers and footers?
iText provides the capability to convert HTML Data to Pdf. Below is the snippet to do it :
Lets assume the html data is available as Input Stream (If its a String then we can convert it to InputStream using Apache Commons - IOUtils)
InputStream htmlData; // Html Data that needs to converted to Pdf
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Document document = new Document();
PdfWriter pdfWriter = PdfWriter.getInstance(document, outputStream);
document.open();
// convert the HTML with the built-in convenience method
XMLWorkerHelper.getInstance().parseXHtml(pdfWriter, document, htmlData);
document.close();
// outputStream now has the required pdf data
I am working as Social Media Developer for Aspose and to add rich text to a form field in PDF file, you can try our Aspose.Pdf for Java API. Check the following sample code:
// Open a PDF document
com.aspose.pdf.Document pdfDocument = new com.aspose.pdf.Document("c:\\data\\input.pdf");
//Find Rich TextBox field using Field Name
RichTextBoxField textBoxField1 = (RichTextBoxField)pdfDocument.getForm().get("textbox1");
//Set the field value
textBoxField1.setValue("<strong> XYZ </strong>");
// Save the modified PDF
pdfDocument.save("c:\\data\\output2.pdf");
I am not trying to market or promote this product. This api actually solved our problem so thought of mentioning it as it might help fellow developers. please let me know if this is against your policy.
I finally realized that the solution for my requirement can not be achieved with either FOP, iText, Aspose, Flying Saucer, JODConverter.
I found a paid api Sferyx. This api allows to render a very complex html to pdf almost preserving the original style. It also renders the images included in the html. We are still exploring this api and will post what other features this api provides.
I am generating PDF documents. It is OK. All works.
I have only one problem: on each PDF page I need about 10 images (QR codes). Is it possible to
put List of java.awt.Image to JasperReport template? Put each image in separate field is complicated...
Example:
In template I have image components with these settings (http://goo.gl/wcESGp):
Expression Class: java.awt.Image
Image Expression :
com.google.zxing.client.j2se.MatrixToImageWriter.toBufferedImage(
new com.google.zxing.qrcode.QRCodeWriter().encode(
$F{CONTENT_TO_ENCODE},
com.google.zxing.BarcodeFormat.QR_CODE, 300, 300))
One image is no problem - just set field in template and put image to field in Java code. How can I fill images in JasperReports report template with List<Image>?
I try to fill a PDF form with PDFBox and I managed to do it well with a portrait oriented document. But I have a problem when filling a document in landscape mode. The fields are filled up, but the text orientation is not good. It appear vertically like if it was still in portrait but in a rotation of 90 degrees.
Here is my simplified code:
PDDocument pdfDoc = PDDocument.load(MY_FILE);
PDDocumentCatalog docCatalog = pdfDoc.getDocumentCatalog();
PDAcroForm acroForm = docCatalog.getAcroForm();
acroForm.getField("aAddressLine1").setValue("ADDRESS1_HERE");
acroForm.getField("aAddressLine2").setValue("ADDRESS1_HERE");
acroForm.getField("country").setValue("COUNTRY_HERE");
pdfDoc.save(PATH_HERE);
pdfDoc.close();
Did you manage to fill a PDF document in landscape mode?
Thanks for your help.
The short answer
I'm afraid PDFBox does not yet (as of version 1.8.2) allow you to fill in landscape PDFs like the one you provided because it does not seem to query and factor in informations about the page the form field is located on.
The long answer
There are different ways you can define a page to be A4 landscape:
You can define it to have the A4 landscape dimensions directly by means of a media box definition:
/MediaBox [0, 0, 842, 595]
In this case the coordinates of your aAddressLine1 would be
/Rect[23.1711 86.8914 292.121 100.132]
or you can define it to have the A4 portrait dimensions and being rotated by 90° (or 270° obviously):
/MediaBox [0, 0, 595, 842]
/Rotate 90
In this case the coordinates of your aAddressLine1 are
/Rect[86.8914 23.1711 100.132 292.121]
Your example document uses the latter method.
Now PDFBox, when creating an appearance stream for that field, only looks at the rectangle defining the field but ignores the properties of the page. Thus, PDFBox sees a very narrow and very high textfield and fills it in just like that. It is completely unaware that the result will be rotated in a PDF viewer.
What it should have done is to also look at the page the field is located on. If that page has a /Rotate entry, it should create an appearance stream for the field which displays the text rotated in the opposite direction.
Alternatives
In a comment you also asked
Do you know another library I could use if PDFBox can't do what I want?
I have tested the feat with iText 5.4.2:
PdfReader reader = new PdfReader(MY_FILE);
OutputStream os = new FileOutputStream(PATH_HERE);
PdfStamper stamper = new PdfStamper(reader, os);
AcroFields acroFields = stamper.getAcroFields();
acroFields.setField("aAddressLine1", "ADDRESS1_HERE");
acroFields.setField("aAddressLine2", "ADDRESS1_HERE");
stamper.close();
(The free iText version is licensed under the AGPL; you have to decide whether that's ok for your project. There is a commercial license, too, if it's not ok.)
I'm sure other PDF libraries also can do that, it's not too exotic a feature after all...
But I also tested PDF Clown 0.1.3 (trunk version), which did not work either:
File file = new File(MY_FILE);
Document document = file.getDocument();
Form form = document.getForm();
form.getFields().get("aAddressLine1").setValue("ADDRESS1_HERE");
form.getFields().get("aAddressLine2").setValue("ADDRESS1_HERE");
file.save(new java.io.File(PATH_HERE), SerializationModeEnum.Incremental);
file.close();