how I can add in my PDF page the header and the footer?
I wanna a table with 3 column in header and other table, 3 column in the footer.
My page could be A3 or A4, and landscape or portrait.
Can anyone help me? I can not found on internet good examples.
Thanks!
Tommaso
Create a class MyPageEventListener that extends PdfPageEventHelper
Add a page event listener to the PdfWriter object
In the onEndPage method of MyPageEventListener class, put the code
for header/footer
Example:
public class MyPageEventListener extends PdfPageEventHelper {
. . .
#Override
public void onEndPage(PdfWriter writer, Document document) {
//code skeleton to write page header
PdfPTable tbl = new PdfPTable(3);
tbl.addCell("1st cell");
tbl.addCell("2nd cell");
tbl.addCell("3rd cell");
float x = document.leftMargin();
float hei = getMyHeaderHeight(); //custom method that return header's height
//align bottom between page edge and page margin
float y = document.top() + hei;
//write the table
tbl.writeSelectedRows(0, -1, x, y, writer.getDirectContent());
}
}
to register the listener simply do
writer.setPageEvent(new MyPageEventListener());
The easiest way to do this is first generate the contents of your entire PDF in memory, then once all the pages have been created you need to open the in-memory PDF in the pdfStamper and iterate through all the pages adding in the header and footer objects are the correct coordinates.
If you do a quick google search of adding page numbers in itextPDF you will find a number of examples that you can quickly adapt for your needs.
The key is that it is done after you create the pdf, not before.
Related
I am attempting to fit all the content of a table to a single A4 PDF.
I found another SO article linked to the itextpdf page here on the same topic
However, I am not certain how it is supposed to be implemented. I have the above code converted to JPype and it seems to run. But I do not get the desired effect.
I want to be able to add images to this table, and have it size appropriately so that it maintains a single A4 page.
Source and example on my github page here:
https://github.com/krowvin/jpypeitext7example
Example PDF
Source
Suppose that this is the table to be fully fit into an A4 page:
Table table = new Table(2);
for (int i = 0; i < 100; i++) {
table.addCell(new Cell().add(new Paragraph(i + " Hello")));
table.addCell(new Cell().add(new Paragraph(i + " World")));
}
Since it's too long to be fully fit via usual layout flow (e.g. Document#add), we should somehow scale it. But first of all, let us find how much space this table occupies if the page to be placed upon is boundless:
LayoutResult result = table.createRendererSubTree().setParent(doc.getRenderer())
.layout(new LayoutContext(new LayoutArea(1, new Rectangle(10000, 10000))));
Rectangle occupiedRectangle = result.getOccupiedArea().getBBox();
Now let's create a form xobject of this table, which we will scale a few lines below:
PdfFormXObject xObject = new PdfFormXObject(new Rectangle(occupiedRectangle.getWidth(), occupiedRectangle.getHeight()));
new Canvas(xObject, pdfDoc).add(table).close();
So now we have the xObject of the table, the only question is how to fit it, e.g. which scale coefficients to apply:
double coefficient = Math.min(PageSize.A4.getWidth() / occupiedRectangle.getWidth(),
PageSize.A4.getHeight() / occupiedRectangle.getHeight());
We're almost done: now let's add the scaled version of the table to the document's page:
new PdfCanvas(pdfDoc.addNewPage())
.saveState()
.concatMatrix(coefficient, 0, 0, coefficient, 0, 0)
.addXObject(xObject)
.restoreState();
And that's it:
In want to add interactive formfields like checkboxes to a newly created multiple page PDF, in the example from iText the code looks like this:
PdfContentByte canvas = writer.getDirectContent();
Rectangle rect = new Rectangle(180, 806 * 40, 200, 788 * 40);
RadioCheckField checkbox = new RadioCheckField(writer, rect, "box1", "Yes");
PdfFormField field = checkbox.getCheckField();
writer.addAnnotation(field);
ColumnText.showTextAligned(canvas, Element.ALIGN_LEFT, new Phrase("checkbox1", normal), 210, 790 * 40, 0);
But this uses absolute positions and I don't know the position because the content before the field has optional images and text parts, where I don't know how many lines they take.
I am also using Chapters and Sections, so I would like to use something like this:
Section section = chap.addSection(new Paragraph("sectionTitel",header2));
section.add(new Paragraph("line before field"));
//add FormField
section.add(field);
section.add(new Paragraph("line after field"));
Have you an idea how to do something like this or how to get the position from the line before ?
Check this example for displaying checkboxes or radiobuttons without specifying positions. You need to use PdfPTable. http://itextpdf.com/sandbox/acroforms/CreateRadioInTable . There is one issue for displaying radiobuttons on multiple pages which I have posted here Issue with iText RadioCheckField when displayed on multiple pages and still waiting for answers
Is there a way to create a table of contents using Java PDFBox library?
The table of contents should be clickable (jump to the right page)
Thanks.
There's no simple method for doing this, but here's an approach. I haven't figured out how to attach links directly to text, so my approach means you have to draw the annotations as rectangles and the text separately. It's a bit rough around the edges, but it works.
// there are other types of destinations, choose what is appropriate
PDPageXYZDestination dest = new PDPageXYZDestination();
// the indexing is odd here. if you are doing this on the first page of the pdf
// that page is -1, the next is 0, the next is 1 and so on. odd.
dest.setPageNumber(3);
dest.setLeft(0);
dest.setTop(0); // link to top of page, this is the XYZ part
PDActionGoTo action = new PDActionGoTo();
action.setDestination(dest);
PDAnnotationLink link = new PDAnnotationLink();
link.setAction(action);
link.setDestination(dest);
PDRectangle rect = new PDRectangle();
// just making these x,y coords up for sample
rect.setLowerLeftX(72);
rect.setLowerLeftY(600);
rect.setUpperRightX(144);
rect.setUpperRightY(620);
PDPage page = // however you are getting your table of contents page, eg new PDPage() or doc.getDocumentCatalog().getAllPages().get(0)
page.getAnnotations().add(link);
PDPageContentStream stream = new PDPageContentStream(doc, page, true, true);
stream.beginText();
stream.setTextTranslation(85, 600); // made these up, have to test to see if padding is correct
stream.drawString("Page 1");
stream.endText();
stream.close();
Phew! That's a lotta code. That should get you on your way. You can make the rectangle the same color as your document background if you want it to look like they are just clicking a link, but that requires more experimentation.
I currently have a method that looks like this for making checkboxes on my pdf:
private static void createCheckbox(PdfWriter writer, float lowerLeftX, float lowerLeftY, float upperRightX, float upperRightY, String fieldName, boolean startChecked) throws IOException, DocumentException {
RadioCheckField bt = new RadioCheckField(writer, new Rectangle(lowerLeftX, lowerLeftY, upperRightX, upperRightY), fieldName, "Yes");
bt.setCheckType(RadioCheckField.TYPE_CHECK);
bt.setBorderWidth(BaseField.BORDER_WIDTH_THIN);
bt.setBorderColor(Color.BLACK);
bt.setBackgroundColor(Color.WHITE);
bt.setChecked(startChecked);
bt.setOptions(RadioCheckField.READ_ONLY);
PdfFormField ck = bt.getCheckField();
writer.addAnnotation(ck);
}
This lets me send in lower left X and Y coords and upper right X and Y coords in order to make a box. This seems to work fine on the first page of a document where I create checkboxes. If I try making them on later pages, they just don't appear.
Example: I make a PDF form some text on page one, make a new page, add more info plus checkboxes, make a new page, add more info and checkboxes. That last page will not actually display checkboxes even if I use the same code for both pages with checkboxes.
Try putting a different name on each page. Field names are document-wide.
I'm creating a table in iText, but I've a problem with a cell that could be divided by a diagonal line. Someone know how can I do that?
The easiest way would be via an onGenericTag handler in a PdfPageEvent.
You give the contents of that cell a generic tag via Chunk.setGenericTag(String tag), and set up a PdfPageEvent hanlder that will draw your line when that chunk is drawn.
Something like:
public class MyPdfPageEvent extends PdfPageEventHelper {
public void onGenericTag(PdfWriter writer, Document doc, Rectangle rect, String tag) {
PdfContentByte canvas = writer.getDirectContent();
canvas.saveState();
canvas.setColorStroke(Color.BLACK); // or whatever
// You can also mess with the line's thickness, endcaps, dash style, etc.
// Lots of options to play with.
canvas.moveTo(rect.getLeft(), rect.getBottom());
canvas.lineTo(rect.getRight(), rect.getTop());
canvas.stroke();
canvas.restoreState();
}
}
Well. The answer of #Mark Storer was helpful, in this case there was a cell of a table I used "PdfPCellEvent" to inherid this methods.
Thanks Mark!