we use itextpdf and xmlworker APIs ( itextpdf-5.1.1.jar, Xmlworker-1.1.0.jar) for PDF generation tasks in our application. We generate HTML content from XML-XSLT conversion and then use the HTML content to create pdf document.
When we trying to implement pagination ( as 1 of 3, 2 of 3..), we learnt from itextpdf online samples that we always need to create a resultant pdf document apart from the PDF document that we create in order to stamp the page number on the each page content.
This approach brings challenges in removing the intermediate pdf document. Is there any way by which page numbers can be determined during the time we create the pdf very first time so that we will avoid creating one resultant pdf document?
Thanks
Venkat
class TableFooter extends PdfPageEventHelper {
String header;
PdfTemplate total;
public void setHeader(String header) {
this.header = header;
}
public void onOpenDocument(PdfWriter writer, Document document) {
total = writer.getDirectContent().createTemplate(30, 16);
}
public void onEndPage(PdfWriter writer, Document document) {
Font ffont = new Font(Font.FontFamily.UNDEFINED, 7, Font.NORMAL);
PdfPTable table = new PdfPTable(2);
try
{
table.setWidths(new int[]{1,1});
table.setTotalWidth(50);
table.getDefaultCell().setFixedHeight(15);
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
Phrase footer = new Phrase(String.format("%d of", writer.getPageNumber()), ffont);
table.addCell(footer);
PdfPCell cell = new PdfPCell(Image.getInstance(total));
table.addCell(cell);
table.writeSelectedRows(0, -1, 275, 20, writer.getDirectContent());
}
catch(Exception de) {
throw new ExceptionConverter(de);
}
}
public void onCloseDocument(PdfWriter writer, Document document) {
ColumnText.showTextAligned(total, Element.ALIGN_LEFT, new Phrase(String.valueOf(writer.getPageNumber() - 1)), 10, 4, 0);
}
}
Please download the free ebook The Best iText Questions on StackOverflow and read the questions listed in the chapter entitled "Page events". These are some of the questions that were selected for this book:
- How to add multiple headers and footers in pdf using itext
- How to add text as a header or footer?
- Creating table with 2 rows in pdf footer using itext
- ...
You can also look at the keywords page on the official iText site, more specifically at the key word Page X of Y.
In your question, you refer to creating an intermediate document. That's what the TwoPasses example is about. You are asking for a way to add Page X of Y in a single pass. That's what the MovieCountries1 example is about.
class PageXofYHeader extends PdfPageEventHelper {
/** The template with the total number of pages. */
PdfTemplate total;
/**
* Creates the PdfTemplate that will hold the total number of pages.
* @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(
* com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
*/
public void onOpenDocument(PdfWriter writer, Document document) {
total = writer.getDirectContent().createTemplate(30, 16);
}
/**
* Adds a header to every page
* @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(
* com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
*/
public void onEndPage(PdfWriter writer, Document document) {
PdfPTable table = new PdfPTable(2);
try {
table.setWidths(new int[]{48, 2});
table.setTotalWidth(527);
table.setLockedWidth(true);
table.getDefaultCell().setFixedHeight(20);
table.getDefaultCell().setBorder(Rectangle.BOTTOM);
table.getDefaultCell()
.setHorizontalAlignment(Element.ALIGN_RIGHT);
table.addCell(
String.format("Page %d of", writer.getPageNumber()));
PdfPCell cell = new PdfPCell(Image.getInstance(total));
cell.setBorder(Rectangle.BOTTOM);
table.addCell(cell);
table.writeSelectedRows(0, -1, 34, 803,
writer.getDirectContent());
}
catch(DocumentException de) {
throw new ExceptionConverter(de);
}
}
/**
* Fills out the total number of pages before the document is closed.
* @see com.itextpdf.text.pdf.PdfPageEventHelper#onCloseDocument(
* com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
*/
public void onCloseDocument(PdfWriter writer, Document document) {
ColumnText.showTextAligned(total, Element.ALIGN_LEFT,
new Phrase(String.valueOf(writer.getPageNumber() - 1)),
2, 2, 0);
}
}
As you can see, we create a small place holder named total
in the onOpenDocument()
method. As we don't know in advance what the total number of pages will be, we add this placeholder to each page without knowing what the page total will be. We only know the final page count when we close the document, and that's why we wait until the onCloseDocument()
method is triggered to add content to the placeholder.