easytable icon indicating copy to clipboard operation
easytable copied to clipboard

Table does not render properly when using colspan and relatively large data

Open pradhan-v opened this issue 4 years ago • 2 comments

The table renders fine when using small strings in the cells. But, when the data in the cells are large...

  • When the table starts, only the header is rendered even though there is space in the page for the first row.
  • The bigger problem is that the table cells are not rendered properly.

Please execute the following code to see the issue.

public class EasytableTest2 {

	private static final String FILE_NAME = "excelLike.pdf";
	private static final float PADDING = 50f;

	public static void main(String[] args) throws IOException {

		createAndSaveDocumentWithTables(new PDDocument(), FILE_NAME, createRegularTable(false),
				createRegularTable(true));
	}

	private static void createAndSaveDocumentWithTables(PDDocument document, String outputFileName, Table... tables)
			throws IOException {

		final PDPage page = new PDPage(PDRectangle.A4);
		document.addPage(page);
		float startY = page.getMediaBox().getHeight() - PADDING;

		try (final PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
			for (final Table table : tables) {
				TableDrawer.builder()//
						.page(page)//
						.contentStream(contentStream)//
						.table(table)//
						.startX(PADDING)//
						.startY(startY)//
						.endY(PADDING)//
						.build()//
						.draw(() -> document, () -> new PDPage(PDRectangle.A4), PADDING);
				startY -= (table.getHeight() + PADDING);
			}
		}
		document.save(outputFileName);
		document.close();
	}

	private static Table createRegularTable(boolean large) {

		return Table.builder().addColumnsOfWidth(150, 150, 150).borderWidth(0.25f)//
				.addRow(Row.builder()//
						.add(TextCell.builder().text("head 1").backgroundColor(Color.LIGHT_GRAY).build())//
						.add(TextCell.builder().text("head 2").backgroundColor(Color.LIGHT_GRAY).build())//
						.add(TextCell.builder().text("head 3").backgroundColor(Color.LIGHT_GRAY).build())//
						.build())//
				.addRow(Row.builder()//
						.add(TextCell.builder().text("row span 4").rowSpan(4).build())//
						.add(TextCell.builder().text("row span 2 1").rowSpan(2).build())//
						.add(TextCell.builder().text(dummyData("data 1", large)).build())//
						.build())//
				.addRow(Row.builder()//
						.add(TextCell.builder().text(dummyData("data 2", large)).build()).build())//
				.addRow(Row.builder()//
						.add(TextCell.builder().rowSpan(2).text("row span 2 2").build())//
						.add(TextCell.builder().text(dummyData("data 3", large)).build())//
						.build())//
				.addRow(Row.builder()//
						.add(TextCell.builder().text(dummyData("data 4", large)).build())//
						.build())//
				.build();
	}

	private static String dummyData(String str, boolean gen) {
		if (!gen) {
			return str;
		}
		StringBuilder sb = new StringBuilder(str);
		for (int i = 0; i < 50; i++) {
			sb.append(str);
		}
		return sb.toString();
	}
}

pradhan-v avatar Jul 18 '20 05:07 pradhan-v

Hi @pradhan-v,

Indeed: that doesn't look very nice. The problem here is that the first row is too big: since the cells on the right are increasing the size of the cell on the left (the one with rowspan) and since the first row is now too big to be drawn on one page it doesn't render correctly.

The question is: what would be a correct rendering? We would need to somehow split the cell on the left over the page border. But there is no concept of cell splitting in easytable.

The "fix" will most probably be that an exception will be thrown in such cases as is already if a single cell is too big.

Anyway: You could work around by using regular cells on the left side that have no borders in between i.e. setting border width to 0 for bottom/top borders.

Hope this helps, Stefan

vandeseer avatar Jul 20 '20 04:07 vandeseer

Hi @vandeseer

Throwing an exception also would leave the rowSpan feature unusable :(. May be draw the cell with the height set to the table height (endY?). Carry over the remaining height to the next page ?

Setting the top/bottom border widths to 0 does the trick. But, it leaves "holes" at the bottom of the table when the "row spanned" cells span across multiple pages. This is okay, for now.

Thanks. Pradhan.

pradhan-v avatar Jul 21 '20 09:07 pradhan-v