1

Using iTextSharp, how can I insert a new page at the beginning of the page, when the PdfWriter has been writing pages already? Suppose the case of an index page which should be the first page of the document, but you wouldn't know its contents until you write the whole document. Particularly, on which page is each section/chapter written.

Matias Bello
  • 50
  • 2
  • 10

1 Answers1

2

You can't go back to the first page while you're creating a document, but there are different ways to solve your problem.

If you don't expect to have many pages, you could consider the solution that is explained in chapter 5 of iText in Action - Second Edition, more specifically in the MovieHistory1.java example.

In this example, we reorder the pages right before we close the document:

// step 1
Document document = new Document();
// step 2
PdfWriter writer
    = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
// IMPORTANT: set linear page mode!
writer.setLinearPageMode();
// step 3
document.open();
// step 4
// Add all your content
// Create a new order for the pages
int total = writer.reorderPages(null);
// change the order
int[] order = new int[total];
for (int i = 0; i < total; i++) {
    order[i] = i + toc;
    if (order[i] > total)
        order[i] -= total;
}
// apply the new order
writer.reorderPages(order);
// step 5
document.close();

Why do I only recommend this for documents with a limited number of pages? For this functionality to work we need to create a linear page tree:

writer.setLinearPageMode();

A linear page tree is not really a tree (it's a tree without any branches) and that is not optimal in PDF.

It is better to reorder the pages in a second go. This is explained in two questions that are bundled in The Best iText Questions on StackOverflow (a free ebook).

The questions were:

I know that having redundant info on SO is not ideal, but this is the code you'd need:

PdfReader reader = new PdfReader(baos.toByteArray());
int n = reader.getNumberOfPages();
reader.selectPages(String.format("%d, 1-%d", n, n-1));
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(filename));
stamper.close();
Community
  • 1
  • 1
Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
  • First of all, thanks for helping me out! Secondly, it *almost* worked, but I still have a problem: the number of pages being handled by the .ReorderPages() method. Actually, writer.CurrentPageNumber and writer.PageNumber both give me the correct number of pages, but writer.ReorderPages(null) it always gives me number of pages -1, and if I try to set an int array with the new order plus 1 more page (matching the real page count), the writer.reorderPages(order); blows because it says the array exceeds the number of pages, which makes sense. – Matias Bello Mar 23 '15 at 15:55
  • If you work with `writer.CurrentPageNumber`, make sure to subtract one, because page numbers start counting at 1, but the reordering index starts counting at 0. – Bruno Lowagie Mar 23 '15 at 16:00
  • It's not that. The document actually has 24 pages, but writer.ReorderPages(null) returns 23, so it expects an array with 23 items. It re-orders correctly, but it's leaving the last page (the 24th page) at the end (where it was) because it omits that page as it thinks there are only 23 and not 24. – Matias Bello Mar 23 '15 at 16:23
  • This has always worked for me. I really think you are confused because of pages starting to count at 1 and order starting to count at 0. In any case: it works perfectly in Java. I don't see why it wouldn't work in C#. Just create your own array with 23 items, for instance counting down from 23 to 0, just for testing. – Bruno Lowagie Mar 23 '15 at 16:34
  • I am not confused, it's not a matter of index count. The pdf file has 24 pages, and the writer.ReorderPages(null) returns 23. Hence, the last page it's ignored (which is, actually, the one I'm wanting to have at the beginning of the document). The C# port may have a bug there, that I don't know.. – Matias Bello Mar 23 '15 at 17:17
  • The method returns 23 which means there are 24 pages. I'm very sorry that you don't believe me... – Bruno Lowagie Mar 23 '15 at 19:03
  • Not that I don't believe you Bruno! I didn't understand. Sorry for that misunderstanding. – Matias Bello Mar 23 '15 at 19:09
  • Thinking a different approach, and considering I'm only needing two or three values to be written after all the rest of the content is written, I was thinking of using AcroFields.. I mean, writing this first page at first, with two or three AcroFields (to be filled in later..) and then, once all the pages have been written, go back to those AcroFields in the first page and filled them in. Is it possible? If so, how? – Matias Bello Mar 23 '15 at 19:32
  • It is night. Let's sleep over it. The AcroFields approach is worse than the `selectPages()` approach. – Bruno Lowagie Mar 23 '15 at 19:39
  • I had the same problem as Bruno - solved by adding a page (`NewPage`) just before calling `ReorderPages` – Muleskinner Feb 09 '16 at 12:52