Working on a calendar projcet and using iText to generate a pdf to print appointments. I can plot a cell with a colspan, and a cell with a rowspan, but I can't combine it. Table has width of 4 cells. I want to achieve something like this:
(A)(B)(C)(C)
(D)(E)(C)(C)
so (1,1), (1,2) and (2,1) (2,2) are regular cells. But there should be a cell in (1,3) covering (1,3) (1,4) (2,3) and (2,4) thus having a colspan of 2 AND a rowspan of 2.
Current code:
PdfPTable table = new PdfPTable(4);
PdfPCell cell = new PdfPCell(new Phrase(" 1,1 "));
table.addCell(cell);
cell = new PdfPCell(new Phrase(" 1,2 "));
table.addCell(cell);
PdfPCell cell23 = new PdfPCell(new Phrase("multi 1,3 and 1,4"));
cell23.setColspan(2);
cell23.setRowspan(2);
table.addCell(cell23);
cell = new PdfPCell(new Phrase(" 2,1 "));
table.addCell(cell);
cell = new PdfPCell(new Phrase(" 2,2 "));
table.addCell(cell);
// 2,3 and 2,4 should be filled because 1,3 has rowspan 2 and colspan 2.
//table.completeRow(); //no effect
However that generates an error:
ExceptionConverter: java.io.IOException: The document has no pages.
If i don't start creating the second row, it just plots fine ( 1 row, and cell on (1,3) has a colspan of 2. Since there is no second row, the rowspan(2) has no effect.
Any help is appreciated. Thanks
At first sight, I'd say: you get a "document has no pages" exception because you're not adding any content to the document. I don't see:
document.add(table);
anywhere in your code snippet.
I have copy/pasted your code into a full example and I posted the full example here: ColspanRowspan. The resulting PDF looks like this:
This seems to be the desired behavior. I can only think of two differences: (1) you're forgetting to add the actual table (which was my initial answer), or (2) you are using a mighty old version of iText in which rowspan wasn't fully supported.
Related
I am trying to merge two columns of one row to make one long line of text without any vertical separation by the cell borders. Here's what I have so far:
CellRangeAddress mergedRegion = new CellRangeAddress(0,0,0,1);
sheet.addMergedRegion(mergedRegion);
XSSFRow row = sheet.createRow(mergedRegion.getFirstRow());
XSSFCell cell = row.createCell(mergedRegion.getFirstColumn());
cell.setCellValue("some string");
Is this the correct way to set the cells contents? In my Junits do I refer to this merged region like this:
assertEquals(workbook.getSheetAt(0).getRow(mergedRegion.getFirstRow())
.getCell(mergedRegion.getFirstColumn()).getStringCellValue(),"some string");
It is probably easier to set the cell contents before you create the merged region. So for example you could:
Row row = sheet.createRow(1);
Cell cell = row.createCell(1);
cell.setCellValue("some string");
sheet.addMergedRegion(new CellRangeAddress(1, 1, 1, 5));
This would add a merged region in columns 1-5 of row 1
I need your help in setting the length of a cell's bottom border. Currently, it is showing the bottom border of a cell too long and I need to shorten it. I tried to change the width of the table, but it is not coming properly.
Below is the code:
Paragraph tableParagraph = new Paragraph();
tableParagraph.setAlignment(Element.ALIGN_LEFT);
PdfPTable table55 = new PdfPTable(2);
table55 = new PdfPTable(new float[] { 6, 6 });
table55.setWidthPercentage(90f);
table55.getDefaultCell().setBorder(PdfPCell.NO_BORDER);
PdfPCell cel2a = new PdfPCell(new Paragraph("Total of Net Profit ", font));
PdfPCell cel2b = new PdfPCell(new Paragraph("100.000" + " USD ", font));
cel2a.setBorder(Rectangle.NO_BORDER);
cel2b.setBorder(Rectangle.BOTTOM);
cel2a.setLeading(1f, 1.5f);
cel2b.setLeading(1f, 1.5f);
table55.addCell(cel2a);
table55.addCell(cel2b);
There are different ways to define the width of a cell. To explain the different options, we have to talk about defining the width of the table (all columns) first, and then talk about defining the width of the separate columns.
Width of a table:
Option 1: You don't define an absolute width.
Instead you ask iText to calculate the width based on the available space. The available space is the width of the page minus the size of the left and the right margin.
If you create a document like this:
Document document = new Document();
Then the width of the page is 595 user units (this is the width of an A4 page) and the width of the margins is 36 user units (these are default values if you don't define the margins explicitly). Hence the available width is 523 user units.
When you define your table like this:
PdfPTable table = new PdfPTable(2);
then the table will take up 80% of the available width when you add this table to a page. So if there's an available width of 523, the width of your table will be 418.4 user units.
You can change this by changing the width percentage. For instance if you add:
table.setWidthPercentage(100);
then 100% of the available width will be used and your table will be 523 user units wide.
Option 2: You define an absolute width.
Suppose that you are asked to create a table with a width of 4 inches. By default 1 inch is 72 user units, so you need a table of 288 user units.
This can be achieved like this:
PdfPTable table = new PdfPTable(2);
table.setTotalWidth(288);
table.setLockedWidth(true);
If you forget the line table.setLockedWidth(true); then iText will assume that you want iText to calculate the width based on the (default) width percentage and the available width. Locking the width, switches iText to use the total width as an absolute width.
Width of columns:
Case 1: relative widths
When you don't define any widths, each column will have the same width. This width will be calculated by dividing the width of the table by the number of columns. E.g. if the width of the table is 288 user units, and if the table has two columns, each column will be 144 user units.
Suppose that you want the second column to be three times as wide as the first column, then you can change the relative widths of the columns like this:
PdfPTable table = new PdfPTable(2);
table.setWidths(new float[] { 1, 3 });
or, if you want to use only one line:
PdfPTable table = new PdfPTable(new float[] { 1, 3 });
If the width of table is 288, the width of the first column will now be 72 and the width of the second column will be 216.
You'll get the same result if you do this:
PdfPTable table = new PdfPTable(new float[] { 25, 75 });
The widths are relative values. { 1, 3 } is the equivalent of { 25, 75 }.
You did something strange:
PdfPTable table55 = new PdfPTable(2);
table55 = new PdfPTable(new float[] { 6, 6 });
In the first line you create a table with two columns of identical width new PdfPTable(2), but you never use that PdfPTable(2), because in the second row you redefine the table55 variable as new PdfPTable(new float[]{ 6, 6 } ).
As { 6, 6 } are relative values, this is equivalent to { 50, 50 } or { 1, 1 }... You're creating a table with two columns with the same width.
Case 2: absolute widths
Suppose that you don't want to use relative widths (for instance because the Math of calculating 1/4 of 288 and 3/4 of 288 is too hard) and you want to create a table width two columns of which the first one is 1 inch wide and the second one is 3 inches wide, then you can once again use the principle of the locked width of a table. Take a look at:
PdfPTable table = new PdfPTable(2);
table.setTotalWidth(new float[]{ 72, 216 });
table.setLockedWidth(true);
Now we pass an array to the setTotalWidth() method. Widths are no longer relative, and we tell iText to use these absolute widths by locking the width.
Now the first column (and all the cells in the first column) will be 72 user units (1 inch) wide and the second column will be 216 user units (3 inch) wide.
Width of the cells:
The width of the cells follow the widths of the columns.
All of this has, of course, been explained in large detail in the documentation that is available online. See for instance examples such as ColumnWidths or the entire chapter that is dedicated to tables in the free ebook The Best iText Questions on StackOverflow. One wonders why no one ever reads that documentation. Does it make sense to keep on answering questions if no one is interested in the answers? (Sorry for this philosophical note, it has been a long day.)
On page I have table, and at the end of the page I have one paragraph, if rows contains small count of rows paragraph must still stay at the end of the page, but if rows too much and table take more than one page paragraph must be just after the table end. At first it looks easy for me and I just set minimum height for PdfPCell which contains table, but then I discover if page is split on pages minimum height apply to each part of table, and because of it paragraph isn't under the table on second page. Is there any solution for it?
I found one not very good solution for this problem, I've added one column to the table, which width it too small and it isn't visible for users, in this column I've add table with two rows, for first row I set minimum height which I need, here the code for creating this additional column
private PdfPCell createMinHeight(float minH) {
PdfPCell cell = new PdfPCell();
PdfPTable table = new PdfPTable(1);
cell.setBorder(Rectangle.NO_BORDER);
table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
table.setHeaderRows(0);
PdfPCell firstRow = new PdfPCell();
firstRow.setBorder(Rectangle.NO_BORDER);
firstRow.setMinimumHeight(minH);
firstRow.setPadding(0);
table.addCell(firstRow);
table.addCell("");
cell.setPadding(0);
cell.addElement(table);
return cell;
}
If I understand you right, you don't want the paragraph splits? You can use setKeepTogether(boolean); for the elements you need:
paragraph.setKeepTogether(true);
or
table.setKeepTogether(true);
Is there a way to add border to a range of cells, using JXL? Setting border for one cell at a time is quite tedious. Choosing a range of cells and merging them works, but not sure how to set border for a bunch of cells at a time.
There is a way, by merging the cells first then add border to one cell
sheet.mergeCells(ColumnX, rowX, columnY, rowX);
WritableCellFormat cellFormat = new WritableCellFormat();
cellFormat.setBorder(Border.ALL, BorderLineStyle.THIN);
jxl.write.Label lab11 = new jxl.write.Label(columnX, rowX, "Label", cellFormat);
smrysheet.addCell(lab11);
using WritableCellFormat
WritableCellFormat cellFormat = new WritableCellFormat();
cellFormat.setBorder(Border.ALL, BorderLineStyle.THIN);
Label label = new Label(col, row, desc, cellFormat);
sheet.addCell(label);
I want to increase the width of the column of excel sheet. as the i am writing trough code is long.
and I need to drag the column manually to see the full text.
I did this –
HSSFRow dataRow = sampleDataSheet.createRow(0);
HSSFCellStyle cellStyle = setHeaderStyle(sampleWorkbook);
cellStyle.setWrapText(true);
***sampleDataSheet.autoSizeColumn(1000000);***
But its not changing anything..
This should work. However,
sampleDataSheet.autoSizeColumn(1000000);
auto-expands column 1000000.
If you want to auto-expand column 0(the first column), use:
sampleDataSheet.autoSizeColumn(0);
To auto-expand column 0 to 9(the first 10 columns):
for (int i=0; i<10; i++){
sampleDataSheet.autoSizeColumn(i);
}
Also, you should create all your rows and fill them with content first, before you call autoSizeColumn(so the column gets the width of the value with the broadest width).
(If you want to set the column width to a fixed value, use HSSFSheet.setColumnWidth(int,int) instead.)
// We can set column width for each cell in the sheet
sheet.setColumnWidth(0, 1000);
sheet.setColumnWidth(1, 7500);
sheet.setColumnWidth(2, 7500);
// By applying style for cells we can see the total text in the cell for specified width
HSSFCellStyle cellStyle = workBook.createCellStyle();
cell.setCellStyle(cellStyle );
cellStyle.setWrapText(true);
sheet.autoSizeColumn(columnNumber) works. this will resize the column to the largest cell length.