0

I need to add 2 tables on 2 parallel columns starting from page 1, and both tables have content more than a single page. Table1 runs on left half of page and table2 runs on right half. I started rendering table 1 and it overflows. Now before proceeding to next page, I want to start rendering table 2 (adding new page makes previous page inaccessible). The implementation of this in iText5 was done using CoulmnText. In iText5, I used 'ColumnText.hasMoreText(status)' to check the overflowing nature of table. But in iText7 this approach is different. This is the sample code in iText7 which i tried to solve the problem stated.

public void createPdf(String dest) throws FileNotFoundException {
    Rectangle[] columnsEven = {new Rectangle(200, 100, 100, 500), new Rectangle(500, 100, 100, 500)};

    PdfWriter writer =new PdfWriter(DEST);
    PdfDocument pdfDoc = new PdfDocument(writer);
    Document document = new Document(pdfDoc);

    Table table1 = new Table(2);
    Table table2 = new Table(2);

    String cellContent1="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam metus elit, ornare et justo nec, ornare dignissim leo. Praesent in egestas erat. Donec id nunc libero. Nullam aliquam sodales sollicitudin. Proin ac egestas nunc. Nunc et suscipit augue. Curabitur porta tempor nunc vel suscipit. Suspendisse imperdiet nunc id quam aliquet fermentum. Pellentesque ut dolor non odio congue blandit. Morbi laoreet magna quam, quis suscipit nunc pulvinar et. Nullam sit amet semper odio, sagittis dictum erat.\n"+

        "Curabitur sagittis arcu turpis, et tincidunt quam congue in. Nullam vitae felis id dui fringilla tincidunt. Nulla ullamcorper nisi non arcu fermentum, eu tempor lectus mattis. Aliquam leo purus, vulputate et ornare in, tincidunt sit amet mi. Sed sollicitudin et sapien vel hendrerit. Morbi id sodales sapien. In non nisl velit. Mauris maximus sodales lectus, ac dignissim elit cursus ac. Nulla viverra, velit sed cursus tincidunt, ex risus posuere diam, lobortis congue metus eros at lorem. Cras a ligula tortor. Vestibulum efficitur diam eros, eget dapibus magna cursus sed.\n"+
        "Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam ut velit pretium diam vestibulum consectetur. Praesent dignissim id sapien eget ultrices. Nam non libero iaculis dolor mattis egestas et quis leo. Sed vitae libero a enim viverra finibus sit amet sed nulla. Sed vitae sem hendrerit, posuere justo sagittis, placerat justo. Aenean felis nisi, tincidunt faucibus sem at, egestas interdum nibh. Curabitur venenatis neque nec volutpat mollis. Phasellus vel tellus ut nisl consequat gravida. Maecenas eget ligula vestibulum, finibus turpis a, hendrerit est. Cras eleifend mollis commodo.\n"+

        "Morbi quam velit, elementum nec turpis porttitor, venenatis sagittis nunc. Sed et nisi ipsum. Maecenas eget tellus in dui condimentum dictum a tempus sem. Maecenas consectetur nisl sit amet accumsan volutpat. Sed dictum massa vitae urna aliquam imperdiet. Nam at ex feugiat dolor vestibulum vehicula. Nullam leo magna, porta ac ex vitae, malesuada fermentum turpis. Donec vel turpis quis ligula feugiat molestie quis at nisi. Quisque efficitur velit odio, id rhoncus diam varius eu. Duis dui mi, scelerisque at faucibus ac, sodales sed est. Sed dictum aliquet semper.\n"+


        "Sed erat ipsum, vehicula nec magna sed, aliquam volutpat lorem. Integer et auctor nisl, at auctor lorem. Nam bibendum urna nec quam cursus, vitae rhoncus justo semper. Morbi posuere dapibus quam vel euismod. Morbi id maximus augue, ut vulputate turpis. Cras posuere auctor justo, in ultricies nunc tincidunt id. Sed luctus nisl lacus, in facilisis erat ultricies id. Aliquam erat volutpat. Morbi accumsan lectus nec dolor ultricies dignissim. Sed quis finibus lectus.\n"+

                "Pellentesque aliquet ex eget cursus accumsan. In ultrices tempus orci sed ultrices. Maecenas lectus nunc, consectetur ac suscipit et, tempus rutrum ipsum. Nulla accumsan tincidunt dignissim. Sed malesuada sapien elit, ac semper urna maximus at. Nunc eleifend tortor nec ligula auctor, sit amet sagittis turpis sagittis. Nam laoreet justo sed gravida iaculis. Fusce ornare quam quis arcu gravida rutrum. Aliquam vitae augue sit amet nisi finibus ullamcorper. Proin quis placerat velit. Integer malesuada erat nec massa tempus pretium.";

    Cell cell = new Cell().add(new Paragraph("INDIA"));
    table1.addCell(cell);   
    table2.addCell(cell);
    cell = new Cell().add(new Paragraph(cellContent1));
    table1.addCell(cell);
    table2.addCell(cell);
    drawTables(pdfDoc, document, new Table[] {table1, table2}, columnsEven);
    document.close();

}

public void drawTables(PdfDocument pdfDoc, Document document, Table[] tables , Rectangle[] rects) {
    // for table 1
    DocumentRenderer renderer1= new MyColumnDocumentRenderer(document, new Rectangle[] {rects[0]});
    document.add(table1);
    // for table 2
    DocumentRenderer renderer2= new MyColumnDocumentRenderer(document, new Rectangle[] {rects[1]});
    document.add(table2);

}
public class MyColumnDocumentRenderer extends DocumentRenderer {
    protected Rectangle column;

    public MyColumnDocumentRenderer(Document document, Rectangle[] column) {
        super(document);
        this.column = column[0];        
    }

    @Override
    protected LayoutArea updateCurrentArea(LayoutResult overflowResult) {
        if(overflowResult!=null && overflowResult.getStatus()== LayoutResult.PARTIAL) {

            column = new Rectangle(300, 100, 200, 600);
        }
        super.updateCurrentArea(overflowResult);


        return (currentArea = new RootLayoutArea(currentPageNumber, column.clone()));
    }

I am migrating iText5 to iText7. Can you suggest me the best approach to implement the problem stated?

I need some help on the questions below as well. Is it possible to process document.add(table1) and document.add(table2) simultaneously? Can we save state of document renderer for one table while we render other table?

  • Your code does not compile – Alexey Subach May 05 '20 at 21:38
  • Updated the code. The output renders table1 completely and then renders table2. But i need to render both the tables from page 1 only side by side. Table1 on left half and table2 on right half of the page. Kindly suggest some solution for this problem. – Onkar Sagar May 06 '20 at 10:40
  • The code still does not compile - `MyColumnDocumentRenderer` is undefined – Alexey Subach May 06 '20 at 19:36

1 Answers1

1

You can always do this in many passes: open the document in stamping mode (with PdfReader and PdfWriter), add the necessary content, close the document, then open the new version of the document, add more content, close the document and so on.

There implementations that are available out of the box do not support your case of simultaneous layouting of several objects across many pages. However, the whole layouting framework is flexible enough so if you dig into the source code a but you can extend from existing implementations and only modify them slightly to achieve your case.

We will extend from ColumnDocumentRenderer to have access to some protected fields and will add a possibility to go back to the first page in the renderer. Please note that in order for this solution to work we need to pass immediateFlush=false to parent's constructor which will increase the memory footprint a bit. Please also note that the solution depends on the implementation details a bit so it might stop working even during a patch upgrade. But this is more of a theoretical possibility, just keep an eye on it.

private static final class ResettingColumnDocumentRenderer extends ColumnDocumentRenderer {
    public ResettingColumnDocumentRenderer(Document document, Rectangle[] columns) {
        super(document, false, columns);
    }

    public void resetToFirstPage() {
        currentArea = null;
        currentPageNumber = 0;
        nextAreaNumber = 0;
    }
}

Now that we have a custom document renderer implementation we can generalize your drawTables method to support case of rendering of N tables:

public void drawTables(Document document, Table[] tables , Rectangle[] rects) {
    for (int i = 0; i < tables.length; i++) {
        ResettingColumnDocumentRenderer renderer = new ResettingColumnDocumentRenderer(document, new Rectangle[] {rects[i]});
        document.setRenderer(renderer);
        document.add(tables[i]);
        renderer.resetToFirstPage();
        renderer.flush();
    }
}

Finally, here is the outer calling code, with almost no modifications compared to your original version:

public void createPdf() throws FileNotFoundException {
    Rectangle[] columnsEven = {new Rectangle(70, 100, 200, 500), new Rectangle(350, 100, 200, 500)};

    PdfWriter writer =new PdfWriter("C:/Users/Alexey/Desktop/23423423.pdf");
    PdfDocument pdfDoc = new PdfDocument(writer);
    Document document = new Document(pdfDoc);

    Table table1 = new Table(2);
    Table table2 = new Table(2);

    String cellContent1="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam metus elit, ornare et justo nec, ornare dignissim leo. Praesent in egestas erat. Donec id nunc libero. Nullam aliquam sodales sollicitudin. Proin ac egestas nunc. Nunc et suscipit augue. Curabitur porta tempor nunc vel suscipit. Suspendisse imperdiet nunc id quam aliquet fermentum. Pellentesque ut dolor non odio congue blandit. Morbi laoreet magna quam, quis suscipit nunc pulvinar et. Nullam sit amet semper odio, sagittis dictum erat.\n"+

            "Curabitur sagittis arcu turpis, et tincidunt quam congue in. Nullam vitae felis id dui fringilla tincidunt. Nulla ullamcorper nisi non arcu fermentum, eu tempor lectus mattis. Aliquam leo purus, vulputate et ornare in, tincidunt sit amet mi. Sed sollicitudin et sapien vel hendrerit. Morbi id sodales sapien. In non nisl velit. Mauris maximus sodales lectus, ac dignissim elit cursus ac. Nulla viverra, velit sed cursus tincidunt, ex risus posuere diam, lobortis congue metus eros at lorem. Cras a ligula tortor. Vestibulum efficitur diam eros, eget dapibus magna cursus sed.\n"+
            "Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam ut velit pretium diam vestibulum consectetur. Praesent dignissim id sapien eget ultrices. Nam non libero iaculis dolor mattis egestas et quis leo. Sed vitae libero a enim viverra finibus sit amet sed nulla. Sed vitae sem hendrerit, posuere justo sagittis, placerat justo. Aenean felis nisi, tincidunt faucibus sem at, egestas interdum nibh. Curabitur venenatis neque nec volutpat mollis. Phasellus vel tellus ut nisl consequat gravida. Maecenas eget ligula vestibulum, finibus turpis a, hendrerit est. Cras eleifend mollis commodo.\n"+

            "Morbi quam velit, elementum nec turpis porttitor, venenatis sagittis nunc. Sed et nisi ipsum. Maecenas eget tellus in dui condimentum dictum a tempus sem. Maecenas consectetur nisl sit amet accumsan volutpat. Sed dictum massa vitae urna aliquam imperdiet. Nam at ex feugiat dolor vestibulum vehicula. Nullam leo magna, porta ac ex vitae, malesuada fermentum turpis. Donec vel turpis quis ligula feugiat molestie quis at nisi. Quisque efficitur velit odio, id rhoncus diam varius eu. Duis dui mi, scelerisque at faucibus ac, sodales sed est. Sed dictum aliquet semper.\n"+


            "Sed erat ipsum, vehicula nec magna sed, aliquam volutpat lorem. Integer et auctor nisl, at auctor lorem. Nam bibendum urna nec quam cursus, vitae rhoncus justo semper. Morbi posuere dapibus quam vel euismod. Morbi id maximus augue, ut vulputate turpis. Cras posuere auctor justo, in ultricies nunc tincidunt id. Sed luctus nisl lacus, in facilisis erat ultricies id. Aliquam erat volutpat. Morbi accumsan lectus nec dolor ultricies dignissim. Sed quis finibus lectus.\n"+

            "Pellentesque aliquet ex eget cursus accumsan. In ultrices tempus orci sed ultrices. Maecenas lectus nunc, consectetur ac suscipit et, tempus rutrum ipsum. Nulla accumsan tincidunt dignissim. Sed malesuada sapien elit, ac semper urna maximus at. Nunc eleifend tortor nec ligula auctor, sit amet sagittis turpis sagittis. Nam laoreet justo sed gravida iaculis. Fusce ornare quam quis arcu gravida rutrum. Aliquam vitae augue sit amet nisi finibus ullamcorper. Proin quis placerat velit. Integer malesuada erat nec massa tempus pretium.";

    Cell cell = new Cell().add(new Paragraph("INDIA"));
    table1.addCell(cell);
    table2.addCell(cell);
    cell = new Cell().add(new Paragraph(cellContent1));
    table1.addCell(cell);
    table2.addCell(cell);
    drawTables(document, new Table[] {table1, table2}, columnsEven);
    document.close();

}
Alexey Subach
  • 11,903
  • 7
  • 34
  • 60
  • Thanks @Alexey. This works perfectly fine. And I can add other needful modifications as per my requirements in this appraoch. This is really helpful. – Onkar Sagar May 07 '20 at 09:57
  • 1
    I have one more question. In the above provided solution by you, we are adding tables and then going back to the first page, and adding another table and so on. Is it possible to start all these n tables on first page first, then add second page and add remaining part of all tables on it, then add third page and so on. So basically, instead of adding the single complete table in one go, can we add parts of multiple tables simultaneously as we proceed by adding pages one by one. Is it possible to do it ? – Onkar Sagar May 07 '20 at 10:10
  • @OnkarSagar that should be possible, but I would not recommend doing it. You will have to perform low-level layout operations on tables which is a more complex thing to do compared to the approach I provided. The idea is the same as you used in your very first question (calling `layout` yourself), but there are many details to it – Alexey Subach May 07 '20 at 19:48
  • @Alexy, I am adding the some more code which I used in iText5. Can you tell how this approach to be implemented in iText7? – Onkar Sagar May 08 '20 at 04:51
  • @OnkarSagar please do not change the intent of the original question. It was answered already. You can ask a new question – Alexey Subach May 08 '20 at 08:12
  • here is the new question. [How to print two parallel tables side by side in iText7, rendering them on one page at at a time and then adding new page](https://stackoverflow.com/questions/61676551/how-to-print-two-parallel-tables-side-by-side-in-itext7-rendering-them-on-one-p) – Onkar Sagar May 08 '20 at 10:59