OpenPDF java grouping elements to stay on the same page - java

I'm using OpenPDF to generate a document.
In this document i want to have certain elements grouped so that they don't get split on a seperate page.
In my case that consists of a paragraph surrounded by 2 lines, 1 above and 1 below.
I've tried grouping them inside a Paragraph element and using the keepTogether property, but then the lines don't show up:
for (final String line : lines) {
Paragraph para = new Paragraph(line, font);
para.setSpacingAfter(20);
doc.add(para);
para.add(new LineSeparator());
para.add(0, new LineSeparator());
para.setKeepTogether(true);
}
Is there any way i can keep these together at all times? or are there better suggestions?
info
language: Java
java version: openjdk 8
OpenPDF version: 1.3.17

I used a table as a workaround like this:
PdfPTable table = new PdfPTable(1);
table.setTotalWidth(527);
table.setLockedWidth(true);
for (final String line : lines) {
PdfPCell cell = new PdfPCell(new Phrase(line, font));
cell.setBorder(Rectangle.BOTTOM | Rectangle.TOP);
cell.setPaddingBottom(20);
cell.setPaddingTop(20);
table.addCell(cell);
}
doc.add(table);

Related

How To Set Data Per Page Itextpdf Java

I made an export pdf system using the java Itext pdf library, but there is a problem when I want to split the data of each page, I want to dynamically divide the data of each page using input, how to do it?like the code below, but the result is not as expected
//looping data row
PdfPTable itemTable = new PdfPTable(headerColumns.length);
itemTable.setWidthPercentage(100);
for(int i = 0;i< data.size();i++){
// header area
PdfPCell area = new PdfPCell(new Phrase(data.get(i).get("area").toString()));
area.setPaddingLeft(4);
area.setVerticalAlignment(Element.ALIGN_MIDDLE);
area.setHorizontalAlignment(Element.ALIGN_CENTER);
itemTable.addCell(area);
// header new_sa
PdfPCell newSa = new PdfPCell(new Phrase(data.get(i).get("new_sa").toString()));
newSa.setPaddingLeft(4);
newSa.setVerticalAlignment(Element.ALIGN_MIDDLE);
newSa.setHorizontalAlignment(Element.ALIGN_CENTER);
itemTable.addCell(newSa);
// header new_sa
PdfPCell saMtd = new PdfPCell(new Phrase(data.get(i).get("sa_mtd").toString()));
saMtd.setPaddingLeft(4);
saMtd.setVerticalAlignment(Element.ALIGN_MIDDLE);
saMtd.setHorizontalAlignment(Element.ALIGN_CENTER);
itemTable.addCell(saMtd);
// header sa_last_month
PdfPCell saLastMonth = new PdfPCell(new Phrase(data.get(i).get("sa_last_month").toString()));
saLastMonth.setPaddingLeft(4);
saLastMonth.setVerticalAlignment(Element.ALIGN_MIDDLE);
saLastMonth.setHorizontalAlignment(Element.ALIGN_CENTER);
itemTable.addCell(saMtd);
//set maxmimum data per page 2
if(itemTable.getRows().size() == 2){
document.newPage();
}
document.add(table);
document.add(itemTable);
}
document.close();
pdf result of the code above
picture page 1
picture page 2
In a comment you clarified
the results that I expect, such as data per page for example 2 , in the results of the image I include it is like a bug where the data on the initial page is 1 but the data is repeated on the 2nd page
If you don't want the data to repeat, then you should not add the same itemTable object again and again but instead create a new one at the start of the loop.
I.e. you should pull the two lines into the loop that currently are before the loop, instead of
PdfPTable itemTable = new PdfPTable(headerColumns.length);
itemTable.setWidthPercentage(100);
for(int i = 0;i< data.size();i++){
...
document.add(itemTable);
}
use
for(int i = 0;i< data.size();i++){
PdfPTable itemTable = new PdfPTable(headerColumns.length);
itemTable.setWidthPercentage(100);
...
document.add(itemTable);
}

Splitting rows of Nested Table OR Inner Table using iTextPDF

How do I split the rows of the inner table. Problem description according to the image.
Here, I have table named PARENT_TABLE that has cell that contains two tables named HEADER_TABLE and CONTENT_TABLE
CONTENT_TABLE has a cell that contains INNER_TABLE. INNER_TABLE contains the dynamic rows/content whose height will be changed according to content.
So, If I make this table using one page it's working perfectly. But incase if I need to split the table in different pages it shows the error like image_2. Please help me out. As a result: The table should look like in the image_1 even if the page split into two or more pages.
Please checkout mentioned image to be more clear.
image_1
Attempt to read from field 'float com.itextpdf.text.pdf.ColumnText.maxY' on a null object reference
image_2
I just found out the solution. The issue occurs only in the case when trying to split the PDFPTable into two pages. I had used tableCell.setRowspan(2), so when trying to split the table above issue occurs.
SOLVED IT: I just made an empty cell in place of using tableCell.setRowspan(2).
private PdfPTable contentWithDateTitleAndDescription(String stringData1, String stringData2, String stringData3, String stringData4) throws IOException, BadElementException {
float relativeWidth[] = {2, 7};
PdfPTable table = new PdfPTable(relativeWidth);
table.setWidthPercentage(100);
PdfPCell cellA = new PdfPCell();
cellA.setBorder(Rectangle.NO_BORDER);
// dateCell.setRowspan(2);
cellA.setPaddingLeft(15);
cellA.setVerticalAlignment(Element.ALIGN_CENTER);
cellA.setPaddingTop(7);
Paragraph dateParagraph = new Paragraph(stringData1);
cellA.addElement(dateParagraph);
PdfPCell emptyCellB = new PdfPCell();
emptyCellB.setBorder(Rectangle.NO_BORDER);
PdfPCell cellC = new PdfPCell();
cellC.setBorder(Rectangle.NO_BORDER);
cellC.setVerticalAlignment(Element.ALIGN_LEFT);
Paragraph titleParagraph = new Paragraph(stringData2 + " / " + stringData3);
cellC.addElement(titleParagraph);
PdfPCell cellD = new PdfPCell();
cellD.setBorder(Rectangle.NO_BORDER);
cellD.setVerticalAlignment(Element.ALIGN_LEFT);
Paragraph descriptionParagraph = new Paragraph(stringData4);
cellD.addElement(descriptionParagraph);
cellD.setPaddingBottom(15);
table.addCell(cellA);
table.addCell(cellC);
table.addCell(emptyCellB);
table.addCell(cellD);
return table;
}

iText: Cell with Image doesn't apply Rowspan

I have a table (2 x 2).
If I add a Phrase as cell in the first cell with rowspan 2, it works. But if I use an Image as cell, rowspan never apply.
float[] rowwidths2 = {0.6f,0.4f};
PdfPTable felsoegyharmad = new PdfPTable(rowwidths2);
felsoegyharmad.setWidthPercentage(100);
PdfPCell kepcell = new PdfPCell(new Phrase("image place", fontAlap));
kepcell.setRowspan(2);
felsoegyharmad.addCell(kepcell);
felsoegyharmad.addCell(new Phrase("1", fontAlap));
felsoegyharmad.addCell(new Phrase("2", fontAlap));
Code above is works as advertise.
But this code under is never rowspanned:
PdfPCell kepcell = new PdfPCell();
kepcell.addElement(Image.getInstance(path));
kepcell.setRowspan(2);
felsoegyharmad.addCell(kepcell);
felsoegyharmad.addCell(new Phrase("1", fontAlap));
felsoegyharmad.addCell(new Phrase("2", fontAlap));
How can I put this image into the first column but in height as two rows?
In case you wonder why nobody is answering your question. That's simple: the problem you describe can not be reproduced. I have taken your code snippet, and I have created the following standalone example:
PdfPTable table = new PdfPTable(2);
PdfPCell imageCell = new PdfPCell();
imageCell.addElement(Image.getInstance(IMG));
imageCell.setRowspan(2);
table.addCell(imageCell);
table.addCell(new Phrase("1"));
table.addCell(new Phrase("2"));
For the full source code, see ImageRowspan
The resulting PDF looks like this:
As you can see, the table has two columns and two rows. The first cell (the one with the image) spans two rows. You can download cmp_image_rowspan.pdf from out git repository.

How to hyphenate text?

I generate an PDF file with iText in Java.
My table columns have fixed widths and text, which is too long for one line is wrapped in the cell.
But hyphenation is not used. The word "Leistungsscheinziffer" is shown as:
Leistungssc //Break here
heinziffer
My code where I use hyphenation:
final PdfPTable table = new PdfPTable(sumCols);
table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
table.getDefaultCell().setPadding(4f);
table.setWidths(widthsCols);
table.setWidthPercentage(100);
table.setSpacingBefore(0);
table.setSpacingAfter(5);
final Phrase result = new Phrase(text, font);
result.setHyphenation(new HyphenationAuto("de", "DE", 2,2));
final PdfPCell cell = new PdfPCell(table.getDefaultCell());
cell.setPhrase(result);
table.addCell(cell);
...
Hyphen is activated and the following test results "Lei-stungs-schein-zif-fer
"
Hyphenator h = new Hyphenator("de", "DE", 2, 2);
Hyphenation s = h.hyphenate("Leistungsscheinziffer");
System.out.println(s);
Is there anything I forgot to set to the table that hyphen is working there?
Thanks for your help. If you need more information about my code, I will tell you.
First a remark that is irrelevant to the problem: you create a PdfPCell object, but you don't use it. You add the phrase to the table instead of using the cell object.
Now for your question: normally hyphenation is set on the Chunk level:
Chunk chunk = new Chunk("Leistungsscheinziffer");
chunk.setHyphenation(new HyphenationAuto("de", "DE", 2,2));
table.addCell(new Phrase(chunk));
If you want to set the hyphenation on the Phrase level, you can do so, but this will only work for all subsequent Chunks that are added. It won't work for the content that is already stored inside the Phrase. In other words: you need to create an empty Phrase object and then add one or more Chunk objects:
Phrase phrase = new Phrase();
phrase.setHyphenation(new HyphenationAuto("de", "DE", 2,2));
phrase.add(new Chunk("Leistungsscheinziffer"));
I've made an example based on your code (HyphenationExample); the word "Leistungsscheinziffer" is hyphenated in the resulting PDF: hyphenation_table.pdf.

iText tables - how to keep multi row cells on one page?

I'm creating a table in iText that lists events for a date. If there are mutliple events for a date, I set the rowspan property of the date-cell to the number of events. I'm currently using a row for each event, since I want to display additional info for the event and want to keep everything aligned.
Basicly my table can look like this:
Date | Event | Details
--------+-----------+---------------
date 1 | event 1 | details 1
--------+-----------+---------------
date 2 | event 2 1 | more
| | details 2 1
+-----------+---------------
| event 2 2 | details 2 2
--------+-----------+---------------
the cell containing date 2 has a rowspan of 2.
I add the table using ColumnText.go() in a loop.
If I write the table to the document and there is only enough space left for event 2 1, event 2 2 goes to the new page. How can I force a new page before adding date 2?
Using PdfPTable.setSplitLate(true) doesn't seem to affect multi row cells. Neither does setting the fixed height of the date 2 cell to the combined heights of the two rows.
one solution would be to use nested tables for column 2 and 3 (and treat column 2 and 3 as one column)
another solution, that doesn't work correctly in the version of iText I'm using would be to use PdfPTable.writeSelectedRows() and write only the (combined) rows that fit on the page. the problem is, that this way the row span is ignored and Date cells look like tey only span one row.
Are there any other ways?
You could create a table for each row and use PdfPTable.setKeepTogether(true) which works in even iText 2.1.7, though I wouldn't recommend staying with that version. Here is an example, where outputFile is a File type variable where the PDF file is being created.
Document document = new Document(new Rectangle(620, 150));
PdfWriter.getInstance(document, new FileOutputStream(outputFile));
document.open();
PdfPTable headerRow = new PdfPTable(3);
headerRow.setKeepTogether(true);
headerRow.addCell("Date");
headerRow.addCell("Event");
headerRow.addCell("Details");
PdfPTable firstRow = new PdfPTable(3);
firstRow.setKeepTogether(true);
firstRow.addCell("date 1");
firstRow.addCell("event 2 1");
firstRow.addCell("more\ndetails 2 1");
PdfPTable secondRow = new PdfPTable(3);
secondRow.setKeepTogether(true);
PdfPCell cell = new PdfPCell(new Phrase("date 2"));
cell.setRowspan(2);
secondRow.addCell(cell);
secondRow.addCell("event 2 1");
secondRow.addCell("more\ndetails 2 1");
secondRow.addCell("event 2 2");
secondRow.addCell("details 2 2");
document.add(headerRow);
document.add(firstRow);
document.add(secondRow);
document.close();
Honestly though, I think the nested table is the better idea.
Document document = new Document(PageSize.A4, 30, 30, 100, 150);
document.SetPageSize(iTextSharp.text.PageSize.A4);
PdfWriter writer = PdfWriter.GetInstance(document, fs);
writer.PageEvent = new ITextEvents();
document.Open();
iTextSharp.text.Font fntHead2 = new iTextSharp.text.Font(bfntHead, 11, 1, BaseColor.BLACK);
Paragraph para = new Paragraph();
Chunk glue = new Chunk(new VerticalPositionMark());
Phrase ph1 = new Phrase();
Paragraph main = new Paragraph();
ph1.Add(new Chunk("Left Side", fntHead2));
ph1.Add(glue); // Here I add special chunk to the same phrase.
ph1.Add(new Chunk("Right Side", fntHead2));
para.Add(ph1);
document.Add(para);

Categories