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
Related
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;
}
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");
I need to make PDF sample file just like the below image but I didn't find any suitable guide to do exactly like this. I have followed some links
http://itextpdf.com/examples/iia.php?id=102
Is there a way to draw a rectangle into a PdfPCell in iText (the Java version)?
but from the second link I didn't understand how could I make more likely to my requirement.
Thanks in advance.
It is unclear to me why you refer to this example: http://itextpdf.com/examples/iia.php?id=102
The PDF that is created with that example shows me in a Superman outfit. What is the link with creating a table with rounded borders?
Please take a look at the NestedTableRoundedBorder example. It creates a PDF that looks like this: nested_table_rounded_border.pdf
This construction consists of nested tables. The outer table only has one column, but we use it to create the rounded corners:
class RoundRectangle implements PdfPCellEvent {
public void cellLayout(PdfPCell cell, Rectangle rect,
PdfContentByte[] canvas) {
PdfContentByte cb = canvas[PdfPTable.LINECANVAS];
cb.roundRectangle(
rect.getLeft() + 1.5f, rect.getBottom() + 1.5f, rect.getWidth() - 3,
rect.getHeight() - 3, 4);
cb.stroke();
}
}
This cell event is used like this:
cell = new PdfPCell(innertable);
cell.setCellEvent(roundRectangle);
cell.setBorder(Rectangle.NO_BORDER);
cell.setPadding(8);
outertable.addCell(cell);
The inner tables are used to create cells with or without borders, for instance like this:
// inner table 1
PdfPTable innertable = new PdfPTable(5);
innertable.setWidths(new int[]{8, 12, 1, 4, 12});
// first row
// column 1
cell = new PdfPCell(new Phrase("Record Ref:"));
cell.setBorder(Rectangle.NO_BORDER);
innertable.addCell(cell);
// column 2
cell = new PdfPCell(new Phrase("GN Staff"));
cell.setPaddingLeft(2);
innertable.addCell(cell);
// column 3
cell = new PdfPCell();
cell.setBorder(Rectangle.NO_BORDER);
innertable.addCell(cell);
// column 4
cell = new PdfPCell(new Phrase("Date: "));
cell.setBorder(Rectangle.NO_BORDER);
innertable.addCell(cell);
// column 5
cell = new PdfPCell(new Phrase("30/4/2015"));
cell.setPaddingLeft(2);
innertable.addCell(cell);
// spacing
cell = new PdfPCell();
cell.setColspan(5);
cell.setFixedHeight(3);
cell.setBorder(Rectangle.NO_BORDER);
innertable.addCell(cell);
If some of the dimensions are quite like you want, it's sufficient to change parameters such as the widths array, the padding, the fixed height, etc.
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);
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 |
|_______________________|