I am trying to set a list of images in a PDF document using iText with Java, i could just insert some of them in the first page but i don't know how to jump to the next pages in order to put the rest of my pictures
for(int i = 0; i < 25; i++) {
Image myImg = Image.getInstance("/home/code/img"+i+".png");
imgPaper.setAbsolutePosition(50, 728-(y*58));
document.add(myImg);
y++;
}
The OP clarified his question in a comment
i have already another pages, i just want how to jump to themĀ
You seem to be creating a new document using a PdfWriter. That class is designed to create a pdf one page after the other. As soon as you start a new page, all former ones are written to file.
Thus, in this process you cannot jump to arbitrary pages. You have to add all information for a page while it is the current one.
If, after creating a multi page document, you need to manipulate the content of its pages, first close the document (finishing it), read it into a PdfReader, and apply a PdfStamper which allows you to manipulate arbitrary pages of an existing PDF.
Alternatively, especially if your images constitute something like a water mark or header/footer Logos, consider using page events in your pdf creation process with the PdfWriter.
try to add a new line to your document
document.add( Chunk.NEWLINE );
link for info:
How to insert blank lines in PDF?
Related
I am new to itext in java. I have an existing pdf of 2 pages. I need to add 2 new pages to it and then add an image to the 3rd page and then add four small rectangles and some text in the 4th page. On searching I got codes for adding new pages and codes for adding images to the existing pdf separately. Column text was used to add text to a new page, I searched for adding image to column text but I cannot find it. getUnderContent helped me to add image at the bottom of 2nd page. I want the image to be added in 3rd page. And the 4th page gets more complicated. I add the rectangle and text using PdfContentByte. This should be done by creating a new page. Any ideas?
Based on your comments, I assume that you are using PdfStamper and that you're able to add an image to an existing page. This is, for instance, done using getUnderContent() and its addImage() method. Now you need to add an extra page.
In PdfStamper, you can use the insertPage() method to achieve this:
stamper.insertPage(pageNum, rectangle);
In this line pageNum is an int value indication the page number where you want to insert the new page, and rectangle is the size of the page. For instance:
stamper.insertPage(reader.getNumberOfPages() + 1, reader.getPageSize(1));
Once you have inserted the page, you can get the "over" or "under" content, and add an image to that PdfContentByte using the addImage() method. You might want to replace reader.getPageSize(1) with a Rectangle object that corresponds with the dimensions of the image.
I want to add a piece of text to every page of a PDF file. This answer in SO works fine. But, the text is added to the top of the page. I would like to add my text to the bottom of each page. How do I do this?
Here is the relevant part of the code.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
// Create a new page in the target for each source page.
while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
document.newPage();
pageOfCurrentReaderPDF++;
currentPageNumber++;
page = writer.getImportedPage(pdfReader, pageOfCurrentReaderPDF);
cb.addTemplate(page, 0, 0);
document.add(new Paragraph("My Text here")); //As per the SO answer
}
pageOfCurrentReaderPDF = 0;
}
The code is part of a function which accepts a folder, reads the PDF files in it and merges them into one single file. So, I would like to add the text in the above loop itself, instead of iterating the file once again.
If you want to automatically add content to every page, you need a page event.
This is explained in chapter 5 of my book" iText in Action - Second Edition".
If you don't own a copy of the book, you can consult the examples here.
You can also find solutions by looking for the keyword Header / Footer.
The example you're referring to doesn't look correct at first sight. Sure, you can use "two passes", one to create the content, and another to add headers or footers, but the suggested solution is different from the recommended solution: http://itextpdf.com/examples/iia.php?id=118
You are copying the mistake in your question: why on earth would you import the document you've just created into a new document, thus throwing away all possible interactivity you've added to that document? It just doesn't make sense. It's unbelievable that this answer received that many up-votes. I'm the original developer of iText and I'm not at all happy with that answer!
In your case, there may be no need to create the document in memory first and to add the footer afterwards. Just take a look at http://itextpdf.com/examples/iia.php?id=104
You need to create a PdfPageEvent implementation (for instance using PdfPageEventHelper) and you need to implement the onEndPage() method.
Documented caveats:
Do not use onStartPage() to add content,
Do not add anything to the Document object passed to the page event,
Unless you specified a different page size, the lower-left corner has the coordinate x = 0; y = 0. You need to take that into account when adding the footer. The y-value for the footer is lower than the y-value for the header.
For more info: consult my book.
Have a look at chapter 6 of iText in Action, 2nd edition, especially at subsection 6.4.1: Concatenating and splitting PDF documents.
Listing 6.22, ConcatenateStamp.java, shows you how you should create a PDF from copies of pages (in your case: all pages) of multiple other PDFs; the sample additionally adds a new "Page X of Y" footer; this demonstrates how you can add content at given positions on the pages while merging the source files.
Perhaps this may be of assistance here... I suspect you want to do something like the following:
cb.addTemplate(page, 0, 0);
document.add(new Paragraph("My Text here"));
document.setFooter(new HeaderFooter("Footnote goes here"));
}
pageOfCurrentReaderPDF = 0;
I have a requirement to insert Content into the middle of the page in a PDF.
The Content may be a Dynamic Table or an Image.
My Concept was to first split the PDF into 2 parts, then get the new Content that is to be added and append by replacing a place holder field.
the Splitting is called Tiling as per IText and here is an example for the same.
http://itextpdf.com/examples/iia.php?id=116
The Code above has 2 drawbacks:
1. It splits the page into 16 parts. but that is part of the example. Still i cant figure out a way to split the file into 2 parts only.
2. secondly the split page is converted to a complete page thus disturbing its proportions.
The Rearranging code is the another problem.
The remaining Content should be re-ordered in append mode. but till yet i have only found codes to add complete new pages rather than just the content.
I have found a code that appends the PDF content by replacing a placeholder:
float[] fieldPosition= pdfTemplate.getAcroFields().getFieldPositions("tableField");
PdfPTable table = buildTable();
PdfContentByte cb = stamper.getOverContent(1);
table.writeSelectedRows(0, -1, fieldPosition[1],fieldPosition[4],cb);
Please help me to solve this requirement.
PDF is a presentation format, not an edition format. In other words, it is not designed to allow content insertion, with the original content reflowing gracefully. As a consequence, no tool (at least, none that I know of, and surely not iText) will enable you to achieve what you were given as a requirement.
My advice :
refuse the assignment since it's not feasible, or
get your hands on the original document, insert the desired extra content, and then convert to PDF.
I am generating a PDF comprised of multiple tables and I want to know if there is a certain way by which I can get to know if the table size will exceed the PDF page size or not. I am using the information to decide wether I will generate the PDF in portrait or landscape mode. Would it be possible to get this size?
know if the table size will exceed the PDF page size
The table size is determined from your XHTML Table Content (rows, columns, headers, footers, etc), plus your CSS doc(s) (width, height and border properties).
The rendering engine (ITextRenderer) only knows your table size, and whether it will fit within a page after it's applied CSS, as part of the process of converting XHTML to rendered output.
So, if you were to query ITextRenderer for this information, you would need to:
Create an ITextRenderer instance, pass your Document in via renderer.setDocument(), and then apply the CSS via renderer.layout(), causing all of the layout calculations to occur based upon the original page orientation
Query somehow to determine if the table fits on the page
If it doesn't, switch between portrait/landscape. But this means changing to a new CSS, setup for a different page shape:
Pick a new CSS, appropriate for the new page orientation and set it within your document
Create a new ITextRenderer instance, pass your Document in via renderer.setDocument(), and then apply the CSS via renderer.layout(), causing all of the layout calculations to occur based upon the new page orientation.
Create PDF output via renderer.createPDF().
Problems:
This is inefficient and inelegant processing.
This is doing things the wrong way around. Controlling page layout should be part of the design process, and should be reflected in (a) the content generated (XHTML) and (b) the formatting (CSS). If that's done correctly, there should be no need to do render-time magic to reformat the entire page.
At step (2), there's no simple query interface that will simply tell you if your table fits within a page. Instead, you have to query the formatted output blocks, and try to work out for yourself where your table is and whether it fits in a page. E.g.:
BlockBox root = renderer.getRootBox();
List pageList = root.getLayer().getPages()
PageBox page = (PageBox)pageList.get(2);
List childBoxList = page.getChildren();
Box childBox = (Box)childBoxList.get(0);
// etc... until you locate your table
At step (4), ITextRenderer expects your CSS to be linked from within your XHTML document. That means you first need to modify your XHTML source, then you need to resubmit it to ITextRenderer.
Suggested Alternative:
Do a wireframe/sketch design with 2 scenarios - one for portrait & one for landscape
Determine the size of elements/rows/columns under the 2 scenarios
Determine the condition logic under which you would use each scenario, portrait v landscape. E.g. if I the number of rows is X and the number of columns is Y - then use landscape, ...
Now create the two CSS files
Now, when you generate your XHTML, use the condition logic to link to the correct CSS
I am working with the iText library to do some PDF manipulation in Java, but I am trying to do something in which the iText API is starting to overwhelm me. I really just need a quick tutorial, or some pseudo-code, but here is what I am trying to accomplish:
User selects a series of check boxes, indicating which PDFs he or she wishes to print.
Based on user input, grab 1 - x PDF template files. Each page has a series of AcroFields which need to be filled out.
One such page requires drawing some custom graphics on the PDF, i.e. accessing the PdfContentByte object and manipulating that to insert images and rectangles.
If it possible, I would like to avoid writing temporary PDFs to disk. The previous programmer did this, and it has been messy to deal with that. I'd much prefer to grab the template file, manipulate it in memory and serve it directly to the browser.
I seem to have all the pieces, but I can't quite put it all together. Point #4 is what's been really tripping me up.
TIA.
So, here is the answer I was finally able to come up with:
//Open an input stream to the PDF template
InputStream is = getInputStreamToEachFile();
//Declare a document object, as well as a PdfCopy for
//copying in each PdfFile we open in memory and edit.
Document doc = new Document();
PdfCopy copy = new PdfCopy(doc, outputStreamToBrowser);
//Be sure to open the document or it will throw an exception!
doc.open();
//Since the PdfStamper class wants to output everything to an
//output stream you can declare a ByteArrayOutputStream object
//and direct it there, since we need to tack on more PDFs and
//can't just output to the response's output stream directly.
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(new PdfReader(is), byteStream);
//Pseduocode - set form fields - just check out
//the documentation for AcroFields in the API
//this part is easy.
...
//if form has custom graphics declare a PdfContentByte array
//the 1 argument in the getUnderContent refers to the page number
PdfContentByte cb = stamper.getUnderContent(1);
//pseduocode - do custom graphics. This can be a lot of different things,
//so check the documentation
...
//Wrap things up - set the dyanamic form fields to read only
//and call the stamper's close function to close the streams
stamper.setFormFlatterning(true);
stamper.close()
//Finally, declare a new PdfReader, reading the stamper's byte array stream
//which was declared in memory.
PdfReader outReader = new PdfReader(byteStream.toByteArray());
//Use this function call to add each page that you need. Repeat this process
//for as many PDFs as are being stitched together.
copy.addPage(copy.getImportedPage(outReader,1));
//Finally, tell the browser you are done generating the file, and output it.
//If there are a lot of pages being generated this way, I guess you could use the flush
//function instead, and then call close when they are all done.
copy.close();
Thanks go out to this tutorial which I eventually found on my own:
http://itextpdf.com/examples/iia.php?id=127