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

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);

Related

OpenPDF java grouping elements to stay on the same page

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);

itextpdf table number of columns

I have a list of 100 records and i want to make a table in pdf with 3 columns. My problem is once the pdf file has been made it's 33 rows with 3 columns so it's 99 records not 100. How can i show the other one record in pdf table?
here is my code:
Document document = new Document(PageSize.A4, -60f, -60f, 18f, 5f);
PdfPTable table = new PdfPTable(3);
PdfPCell cell;
if (filterPins.size() > 0) {
for (int i = 0; i < filterPins.size(); i++) {
Bitmap bmp = getRecyclerViewScreenshot(pinList, i);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream);
Image image = Image.getInstance(stream.toByteArray());
cell = new PdfPCell(image, true);
cell.setPadding(0f);
cell.setBorder(Rectangle.NO_BORDER);
table.addCell(cell);
}
File myDirectory = new File(rootView.getContext().getFilesDir(), String.valueOf(factorNo));
if (!myDirectory.exists()) {
myDirectory.mkdirs();
}
File pdfFile = new File(myDirectory, fileName);
PdfWriter.getInstance(document, new FileOutputStream(pdfFile));
document.open();
document.add(table);
document.close();
}
filterPins is my arrayList containing 100 records.
How can i show the other one record in pdf table?
First of all that also is a question you have to ask yourself. Do you want the 100th entry fill only a single of the three cells of a row? If yes, which one? Or should it span the whole row? Or would you prefer yet another construct?
Let's assume, though, you simply want the 100th entry to be the first cell in the 34th row and you also want the other cells in that row to be empty. In that case there is a PdfPTable utility method that fills the current row with empty cells (copies of the default cell):
table.completeRow();
if(yourlist.size() % 3 == 0){
int totalRows = yourlist.size() / 3;
create your pdf.
for example list.size() = 99 then you create 33 rows each row have 3 column.
}
else
{
int totalRows = yourlist.size() / 3;
for example if yourlist.size() = 100.
then first create 33 row each row have 3 column.
remaining 1 item add in new list after created 33 rows.
remaining 1 or 2 column add in new row.
Note : in any case you have remaining only 1 or 2.
}

Aspose Java - Add Table below a list value

The following is the format I want to generate:
From my limited experience of the API I know how to make a list
ListFormat listFormat = builder.getListFormat();
listFormat.setList(document.getLists().add(ListTemplate.NUMBER_DEFAULT));
builder.writeln("Component Specification")
listFormat.setListLevelNumber(1);
builder.writeln("Raw Material Specification")
Now how do I transition from the list to the table below?
writing a new line adds numbers, even in the cells of the table.
If I set the listformat to null then the indentation is lost. I want to maintain the indentation of the list but also add the table below that list value
Anyway to do that?
#Furqan,
You need to set Table LeftIndent property for your requirements. Please check following sample code snippet.
I am Tilal Ahmad, developer evangelist at Aspose.
Document doc= new Document();
DocumentBuilder builder= new DocumentBuilder(doc);
ListFormat listFormat = builder.getListFormat();
listFormat.setList(doc.getLists().add(ListTemplate.NUMBER_DEFAULT));
builder.writeln("Component Specification");
builder.getListFormat().listIndent();
builder.getListFormat().getListLevel().setNumberStyle(NumberStyle.ARABIC);
builder.getListFormat().getListLevel().setNumberFormat("\u0000.\u0001");
builder.writeln("Raw Material Specification");
builder.getListFormat().removeNumbers();
Table table = new Table(doc);
// Add the table to the document.
doc.getFirstSection().getBody().appendChild(table);
Row row1 = new Row(doc);
row1.getRowFormat().setAllowBreakAcrossPages(true);
table.appendChild(row1);
// Create a cell and add it to the row
Cell cell1 = new Cell(doc);
cell1.getCellFormat().getShading()
.setBackgroundPatternColor(Color.LIGHT_GRAY);
cell1.getCellFormat().setWidth(50);
// Add a paragraph to the cell as well as a new run with some text.
cell1.appendChild(new Paragraph(doc));
cell1.getFirstParagraph().appendChild(new Run(doc, "Col1"));
// Add the cell to the row.
row1.appendChild(cell1);
// We would then repeat the process for the other cells and rows in the
// table.
// We can also speed things up by cloning existing cells and rows.
row1.appendChild(cell1.deepClone(false));
row1.getLastCell().appendChild(new Paragraph(doc));
row1.getLastCell().getFirstParagraph()
.appendChild(new Run(doc, "Col2"));
row1.appendChild(cell1.deepClone(false));
row1.getLastCell().appendChild(new Paragraph(doc));
row1.getLastCell().getFirstParagraph()
.appendChild(new Run(doc, "Col3"));
Row row = new Row(doc);
row.getRowFormat().setAllowBreakAcrossPages(true);
table.appendChild(row);
// Create a cell and add it to the row
Cell cell = new Cell(doc);
cell.getCellFormat().setWidth(50);
// Add a paragraph to the cell as well as a new run with some text.
cell.appendChild(new Paragraph(doc));
cell.getFirstParagraph()
.appendChild(new Run(doc, "Row 1, Cell 1 Text"));
// Add the cell to the row.
row.appendChild(cell);
row.appendChild(cell.deepClone(false));
row.getLastCell().appendChild(new Paragraph(doc));
row.getLastCell().getFirstParagraph()
.appendChild(new Run(doc, "Row 1, Cell 2 Text"));
row.appendChild(cell.deepClone(false));
row.getLastCell().appendChild(new Paragraph(doc));
row.getLastCell().getFirstParagraph()
.appendChild(new Run(doc, "Row 1, Cell 3 Text"));
// Add left indent to the table.
table.setLeftIndent(60);
doc.save("E:/Data/Test1.docx");

Strange setRowspan error/not working

I set up a header for my iText-table which has 6 columns, later I wanted to use the very same header for another table and set the colspans more generic, but the one rowspan then doesn't work any more.
This is my original (working) code with the 6 columns:
public static PdfPTable createHeaderContent() {
PdfPTable table = new PdfPTable(6);
table.setWidthPercentage(100);
PdfPCell dobicell = new PdfPCell();
dobicell.setColspan(2);
dobicell.addElement(new Phrase(docType, DOBIFONTADR));
dobicell.setBorder(Rectangle.LEFT | Rectangle.RIGHT | Rectangle.TOP);
table.addCell(dobicell);
dobicell = new PdfPCell();
dobicell.setColspan(2);
dobicell.addElement(new Phrase("Ing. Mario J. Schwaiger", DOBIFONTADR));
dobicell.setBorder(Rectangle.TOP);
table.addCell(dobicell);
dobicell = Dobilogo.getPiccell(92, 104);
dobicell.setBorder(Rectangle.TOP | Rectangle.RIGHT);
dobicell.setColspan(3);
dobicell.setRowspan(2);
table.addCell(dobicell);
dobicell = getKundenCol(kunde);
dobicell.setColspan(2);
dobicell.setBorder(Rectangle.LEFT | Rectangle.RIGHT | Rectangle.BOTTOM);
table.addCell(dobicell);
dobicell = getUserCell(user);
dobicell.setColspan(2);
table.addCell(dobicell);
table.setHeaderRows(1);
return table;
}
The result looks like it should (I've used some nice colouring to indicate the spans:
The modified code for the "general purpose" is pretty much the same:
public static PdfPTable createHeaderContent(int[] coldist) {
PdfPTable table = new PdfPTable(coldist[0] + coldist[1] + coldist[2]); //createHeaderContent(new int[]{4, 7, 4, 4, 7});
table.setWidthPercentage(100);
PdfPCell dobicell = new PdfPCell();
dobicell.setColspan(coldist[0]); //used to be 2, now 4
dobicell.addElement(new Phrase(doctype, DOBIFONTADR));
dobicell.setBorder(Rectangle.LEFT | Rectangle.RIGHT | Rectangle.TOP);
table.addCell(dobicell);
dobicell = new PdfPCell();
dobicell.setColspan(coldist[1]); //used to be 2, now 7
dobicell.addElement(new Phrase("Ing. Mario J. Schwaiger", DOBIFONTTITEL));
dobicell.setBorder(Rectangle.TOP);
table.addCell(dobicell);
dobicell = Dobilogo.getPiccell(92, 104);
dobicell.setBorder(Rectangle.TOP | Rectangle.RIGHT);
dobicell.setColspan(coldist[2]); //used to be 3, now 4
dobicell.setRowspan(2); // <--- This is fishy, but why?
table.addCell(dobicell);
dobicell = getKundenCol(kunde);
dobicell.setColspan(coldist[3]); //used to be 2, now 4
dobicell.setBorder(Rectangle.LEFT | Rectangle.RIGHT | Rectangle.BOTTOM);
table.addCell(dobicell);
dobicell = getUserCell(user);
dobicell.setColspan(coldist[4]); //used to be 2, now 7
table.addCell(dobicell);
table.setHeaderRows(1);
return table;
}
But there is something wrong with the last column:
At first I assumed there's another row hidden and used dobicell.setRowspan(3); but this alters the first data-row already. Trying to add another cell puts it in the first row after the header.
Strangely when I widen the user-cell in the last part to the whole rowspaned cell disappears.
Is there a solution or reason for this issue?
There are two problems here, one which iText seems to ignore and one which causes the problem:
In the original code the cells require 7 columns as they have twice setColspan(2) and once setColspan(3) in a row. But the table is only constructed for 6 columns: new PdfPTable(6).
iText seems to ignore the missing column here...
The code declares the first row to be a header for the table: table.setHeaderRows(1). This clashes with the declaration of the last cell in the first row to span 2 rows setRowspan(2).
iText here ignores the rowspan in the header row resulting in the undesired appearance.
To fix this, don't declare a row span at all or use a row span of at least two (if enough rows are going to follow).
In a comment the OP confirmed
In the modified version I still had setHeaderRows(1). Replacing it with setHeaderRows(2) solved the issue

Nested iText PdfPTable border width

I'm using iTextPdf for pdf generation and I'm creating nested table using the below code.
PdfPTable table = new PdfPTable(3);
PdfPTable nestedTable = new PdfPTable(2);
table.addCell(nestedTable);
Now, I want the border width of table to be 0, i.e invisible. I've checked the api and several posts on SO but I couldn't find anything substantial. Is there a way to do so ?
I'm using iText version 5.1.2
In iText PDF api there is no such property to manipulate border directly however as PdfPCell extends Rectangle it has setBorder to manipulate the border. So I've just used the same as a workaround as provided below:
PdfPTable table = new PdfPTable(2);
PdfPTable nestedTable1 = new PdfPTable(1);
PdfPTable nestedTable2 = new PdfPTable(1);
PdfPCell cell = new PdfPCell(new Phrase("StackOverflow"));
newCell.setBorder(Rectangle.NO_BORDER);
nestedTable1.addCell(cell);
nestedTable2.addCell(new Phrase("StackOverflow"));
cellOne = new PdfPCell(nestedTable1);
cellTwo = new PdfPCell(nestedTable2);
cellOne.setBorder(Rectangle.NO_BORDER);
table.addCell(cellOne);
table.addCell(cellTwo);
Output:
_______________________
| |
StackOverflow | StackOverflow |
|_______________________|

Categories