Unfortunately the proposed event handler cannot be used because of the following reason: eventhough a PdfDocument
is created with immediateFlush
set as true
(by the way, it is its default value, as well PageSize.A4, so no need in specifying it), iText doesn't flush a page (close a page and dispatch an END_PAGE
event) right in the moment when the next one is added to the document. Instead iText waits for one more page to be flushed.
So the event for the first page is called while processing this line:
doc.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
And the event for the second page is called while processing this line (when i equals to 2):
doc.add(table);
I suggest rewriting your event handler. For example, why not to have a map in your handler, where key will represent the first page on which a table occurs and the value - the table's number and the last page, on which it occurs. Then on the handler's level one could just do the following: whenever the event is dispatched, one should search through the map to find a) whether there is a table on the page to be flushed; b) if yes, which table it is.
The following handler is responsible for that (note that the code piece is in Java, but there should be no problem in porting in to .NET, I believe):
public class TabPageHandler implements IEventHandler {
private Map<Integer, PageSpan> tables;
public TabPageHandler() {
this.tables = new HashMap<Integer, PageSpan>();
}
public void addTable(int table, int firstPage, int lastPage) {
tables.put(firstPage, new PageSpan(table, lastPage));
}
int getTable(int page) {
int firstPage = 0;
for (int i = page; i > 0; i--) {
if (null != tables.get(i)) {
firstPage = i;
break;
}
}
if (0 == firstPage || tables.get(firstPage).getLastPage() < page) {
// no table on such a page
return -1;
} else {
return tables.get(firstPage).getTableNum();
}
}
@Override
public void handleEvent(Event event) {
try {
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfDocument pdfDoc = docEvent.getDocument();
PdfPage page = docEvent.getPage();
int pageNumber = pdfDoc.getPageNumber(page);
PdfCanvas canvas = new PdfCanvas(page.newContentStreamBefore(), page.getResources(), pdfDoc);
canvas.beginText().moveText(page.getPageSize().getWidth() / 2, page.getPageSize().getTop() - 35)
.setFontAndSize(PdfFontFactory.createFont(FontConstants.TIMES_ROMAN), 10)
.showText("Number of page " + pageNumber)
.endText();
int table = getTable(pageNumber);
if (-1 != table) {
canvas.beginText().moveText(20, page.getPageSize().getTop() - 20)
.setFontAndSize(PdfFontFactory.createFont(FontConstants.TIMES_ROMAN), 10)
.showText("Table:" + table)
.endText();
}
canvas.release();
} catch (IOException e) {
e.printStackTrace();
}
}
class PageSpan {
private int tableNum;
private int lastPage;
public PageSpan(int tableNum, int lastPage) {
this.tableNum = tableNum;
this.lastPage = lastPage;
}
public int getTableNum() {
return tableNum;
}
public int getLastPage() {
return lastPage;
}
}
}
Now the only question left is how to use such a handler. The answers:
add it to the document right when the document is created. You don't need to remove handlers anymore: everything will be done by the only handler;
before adding a table to the document, call addTable
specifying last page with some unrealisticly big number. One doesn't know how much pages it will take to layout a table, so one should make sure that even a very long table will be handled properly;
once a table is added, one can specify the correct last page of the table (in the map the old pair will just be rewritten).
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outFileName));
Document doc = new Document(pdfDoc);
TabPageHandler handler = new TabPageHandler();
pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, handler);
for (int i = 1; i < 5; i++) {
int firstPage = Math.max(1, doc.getPdfDocument().getNumberOfPages());
Table table = new Table(UnitValue.createPercentArray(1)).useAllAvailableWidth();
table.addHeaderCell(new Paragraph(i + ""));
for (int j = 0; j < 40 * i; j++) {
table.addCell(new Paragraph("aaa"));
}
handler.addTable(i, firstPage, 10000000);
doc.add(table);
int lastPage = doc.getPdfDocument().getNumberOfPages();
handler.addTable(i, firstPage, lastPage);
doc.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
}
doc.close();