0

Am trying to create TOC from merged file and need TOC as my first page.Now am facing an issue when the toc have more data, its over written to same file.my expectation is to create a new page in the existing toc.pdf file and write remaining TOC content.

PdfReader tocReader = new PdfReader("toc.pdf");
page = copy.getImportedPage(tocReader, 1);
stamp = copy.createPageStamp(page);
int tocPageCount = 1;
Paragraph paragraph;
PdfAction action;
PdfAnnotation link;
float y = 770;
PdfImportedPage newPage = null;
Rectangle pagesize = tocReader.getPageSize(1);
ColumnText colTxt = new ColumnText(stamp.getOverContent());
colTxt.setSimpleColumn(36, 36, 559, y);
for (TocModel tocModel : toc) {
    paragraph = new Paragraph(tocModel.getTitle());
    paragraph.add(new Chunk(new DottedLineSeparator()));
    paragraph.add(String.valueOf(tocModel.getPageNo()));
    colTxt.addElement(paragraph);
    colTxt.go();
    // seting toc action
    action = PdfAction.gotoLocalPage("p" + tocModel.getPageNo(), false);
    link = new PdfAnnotation(copy, 36, colTxt.getYLine(), 559, y,action);
    stamp.addAnnotation(link);
    y = colTxt.getYLine();
}

int status = colTxt.go();
status = colTxt.go();
if (ColumnText.hasMoreText(status)) {
    PdfContentByte canvas = stamp.getOverContent();
    canvas.addTemplate(page, 0, 0);
    colTxt.setCanvas(canvas);
    colTxt.setSimpleColumn(new Rectangle(36, 36, 559, 806));
    colTxt.go();
}

stamp.alterContents();
copy.addPage(page);
document.close();
logger.info("Finished TOC !!!");

tocReader = new PdfReader(bos.toByteArray());
noOfPages =tocReader.getNumberOfPages();
tocReader.selectPages(String.format("%d, 1-%d", noOfPages, noOfPages - 1));
PdfStamper stamper = new PdfStamper(tocReader, new FileOutputStream(outPutDirectory + "merge.pdf"));

stamper.close();
logger.info("merging completed!!!");

i refer the following code Adding table to existing PDF on the same page - ITEXT

current output file:

current output file

mkl
  • 90,588
  • 15
  • 125
  • 265
arj
  • 887
  • 1
  • 15
  • 37
  • Have you considered building the toc as a document in its own right using toc.pdf as background for each page and then adding this document to your copy? That way you can leave the layout'ing details to iText... – mkl Aug 07 '17 at 07:44
  • can u please explain little more.give any eample – arj Aug 07 '17 at 13:13

1 Answers1

0

when the toc have more data, its over written to same file.my expectation is to create a new page in the existing toc.pdf file and write remaining TOC content.

As your code does not create an additional page upon overflow, there is none.

In your code you chose not to use the highest level iText API (at that level iText does the layout and page breaking stuff for you) but a medium level API (at this level you do layout and page breaking stuff yourself).

Her two possible solutions, one working along the lines of your existing code, merely fixing it, and one working with the high level API.

Fixing your code

You actually merely have to switch to the next page when your colTxt.go() attempt return code indicates that the line could not be added to the colTxt.

Please replace the section

PdfReader tocReader = new PdfReader("toc.pdf");
...
logger.info("Finished TOC !!!");

by this:

PdfReader tocReader = new PdfReader("toc.pdf");
page = copy.getImportedPage(tocReader, 1);
stamp = copy.createPageStamp(page);
int tocPageCount = 1;
Paragraph paragraph;
PdfAction action;
PdfAnnotation link;
float y = 770;
ColumnText colTxt = new ColumnText(stamp.getOverContent());
colTxt.setSimpleColumn(36, 36, 559, y);
for (TocModel tocModel : toc) {
    paragraph = new Paragraph(tocModel.getTitle());
    paragraph.add(new Chunk(new DottedLineSeparator()));
    paragraph.add(String.valueOf(tocModel.getPageNo()));
    colTxt.addElement(paragraph);
    if (ColumnText.hasMoreText(colTxt.go()))
    {
        stamp.alterContents();
        copy.addPage(page);
        tocReader = new PdfReader("toc.pdf");
        page = copy.getImportedPage(tocReader, 1);
        tocPageCount++;
        stamp = copy.createPageStamp(page);
        y = 770;
        colTxt = new ColumnText(stamp.getOverContent());
        colTxt.setSimpleColumn(36, 36, 559, y);
        colTxt.go();
    }
    // seting toc action
    action = PdfAction.gotoLocalPage("p" + tocModel.getPageNo(), false);
    link = new PdfAnnotation(copy, 36, colTxt.getYLine(), 559, y,action);
    stamp.addAnnotation(link);
    y = colTxt.getYLine();
}

stamp.alterContents();
copy.addPage(page);

document.close();
logger.info("Finished TOC !!!");

(TableOfContents test testAddTocLikeArjImproved)

As you see, as soon as we detect ColumnText.hasMoreText(colTxt.go()), we introduce a new page. As a page stamp actually manipulates the source page (as far as I remember, that is, I hardly ever do this stuff...), we need to import from a fresh reader.

(One can improve the code some more by closing the readers when they are not needed anymore; here we allow them to linger until garbage collection frees them.)

Doing it differently

One can use the iText high level APIs like this.

Please replace the section

PdfReader tocReader = new PdfReader("toc.pdf");
...
logger.info("Finished TOC !!!");

from your code by this:

final PdfReader tocBackgroundReader = new PdfReader("toc.pdf");
Document tocDocument = new Document(tocBackgroundReader.getCropBox(1));
ByteArrayOutputStream tocBaos = new ByteArrayOutputStream();
PdfWriter tocWriter = PdfWriter.getInstance(tocDocument, tocBaos);
tocWriter.setPageEvent(new PdfPageEventHelper() {
    PdfImportedPage stationary = tocWriter.getImportedPage(tocBackgroundReader, 1);
    @Override
    public void onEndPage(PdfWriter writer, Document document)
    {
        writer.getDirectContentUnder().addTemplate(stationary, 0, 0);
    }
});
tocDocument.open();
for (TocModel tocModel : toc) {
    PdfAction action = PdfAction.gotoLocalPage("p" + tocModel.getPageNo(), false);

    Paragraph paragraph = new Paragraph();
    Chunk chunk = new Chunk(tocModel.getTitle());
    chunk.setAction(action);
    paragraph.add(chunk);
    chunk = new Chunk(new DottedLineSeparator());
    chunk.setAction(action);
    paragraph.add(chunk);
    chunk = new Chunk(String.valueOf(tocModel.getPageNo()));
    chunk.setAction(action);
    paragraph.add(chunk);
    tocDocument.add(paragraph);
}
tocDocument.close();

PdfReader tocReader = new PdfReader(tocBaos.toByteArray());
int tocPageCount = tocReader.getNumberOfPages();
copy.addDocument(tocReader);

document.close();
logger.info("Finished TOC !!!");

(TableOfContents test testAddTocLikeArjAlternative)

Making the re-ordering work

Your page re-ordering only supports a single page.

Please replace

tocReader.selectPages(String.format("%d, 1-%d", noOfPages, noOfPages - 1));

by

tocReader.selectPages(String.format("%d-%d, 1-%d", noOfPages - tocPageCount + 1, noOfPages, noOfPages - tocPageCount));
Community
  • 1
  • 1
mkl
  • 90,588
  • 15
  • 125
  • 265