Java使用easytable通过for循环批量生成表格数据行的实现问题
问题背景
我正在尝试使用vandeseer的easytable库创建包含表头行、且剩余数据行通过for循环生成的表格。目前我仅能实现创建两个独立表格上下对齐摆放,第一个表格存放表头行,第二个表格用来承载for循环生成的多行内容,使用PDFBox渲染后的效果如下:
我当前的实现代码如下:
private void drawActiveCelUserRolesTable(PDPageContentStream contentStream, List<CelUser> users) { //draw table header Table activeUsersHeader = Table.builder() .addColumnsOfWidth(100,100,100,100,100) .addRow(Row.builder() .add(TextCell.builder().text("Last Name").borderWidth(1).build()) .add(TextCell.builder().text("First Name").borderWidth(1).build()) .add(TextCell.builder().text("Role Name").borderWidth(1).build()) .add(TextCell.builder().text("Effective Date").borderWidth(1).build()) .add(TextCell.builder().text("Expiry Date").borderWidth(1).build()) .build()) .build(); TableDrawer headerDrawer = TableDrawer.builder() .contentStream(contentStream) .startX(HEADER_TABLE_LOCATION_X) .startY(HEADER_TABLE_LOCATION_Y-50) .table(activeUsersHeader) .build(); headerDrawer.draw(); Table activeUsersRows = Table.builder() .addColumnsOfWidth(100,100,100,100,100) .addRow(Row.builder() .add(TextCell.builder().text("Joe").borderWidth(1).build()) .add(TextCell.builder().text("Bob").borderWidth(1).build()) .add(TextCell.builder().text("ADM").borderWidth(1).build()) .add(TextCell.builder().text("17/12/20").borderWidth(1).build()) .add(TextCell.builder().text("17/12/21").borderWidth(1).build()) .build()) .build(); TableDrawer rowDrawer = TableDrawer.builder() .contentStream(contentStream) .startX(HEADER_TABLE_LOCATION_X) .startY(HEADER_TABLE_LOCATION_Y - 67) .table(activeUsersRows) .build(); rowDrawer.draw(); }
我尝试通过如下写法用for循环填充表格行,但是代码显然无法正常运行:
Table activeUsersRows = Table.builder() .addColumnsOfWidth(100,100,100,100,100) for (int i = 0; i < 5; i++) { .addRow(Row.builder() .add(TextCell.builder().text("Joe").borderWidth(1).build()) .add(TextCell.builder().text("Bob").borderWidth(1).build()) .add(TextCell.builder().text("ADM").borderWidth(1).build()) .add(TextCell.builder().text("17/12/20").borderWidth(1).build()) .add(TextCell.builder().text("17/12/21").borderWidth(1).build()) .build()) .build(); }
我查阅了官方文档,没有找到类似的实现案例。我也见过使用Table.TableBuilder的示例,但不知为何这类写法生成的表格无法在PDF中渲染,因此我目前仅使用Table类实现。请问我要如何正确通过for循环在同一个easytable表格中批量生成数据行?
解决方案
你原来的写法错误是因为Java的链式调用不能中间插入for循环语句,正确的做法是先单独实例化TableBuilder对象,循环调用addRow方法,最后再调用build生成Table对象即可,不需要拆成两个独立表格。
完整的修正后代码如下:
private void drawActiveCelUserRolesTable(PDPageContentStream contentStream, List<CelUser> users) throws IOException { // 先创建TableBuilder对象,不要直接链式build Table.TableBuilder tableBuilder = Table.builder() .addColumnsOfWidth(100,100,100,100,100); // 先添加表头行 tableBuilder.addRow(Row.builder() .add(TextCell.builder().text("Last Name").borderWidth(1).build()) .add(TextCell.builder().text("First Name").borderWidth(1).build()) .add(TextCell.builder().text("Role Name").borderWidth(1).build()) .add(TextCell.builder().text("Effective Date").borderWidth(1).build()) .add(TextCell.builder().text("Expiry Date").borderWidth(1).build()) .build()); // 循环添加数据行,这里可以遍历你传入的users集合替换示例内容 for (CelUser user : users) { tableBuilder.addRow(Row.builder() .add(TextCell.builder().text(user.getLastName()).borderWidth(1).build()) .add(TextCell.builder().text(user.getFirstName()).borderWidth(1).build()) .add(TextCell.builder().text(user.getRoleName()).borderWidth(1).build()) // 日期格式化可以根据你的需求自行调整 .add(TextCell.builder().text(user.getEffectiveDate().format(DateTimeFormatter.ofPattern("dd/MM/yy"))).borderWidth(1).build()) .add(TextCell.builder().text(user.getExpiryDate().format(DateTimeFormatter.ofPattern("dd/MM/yy"))).borderWidth(1).build()) .build()); } // 所有行添加完成后再build生成完整表格 Table fullTable = tableBuilder.build(); // 一次性渲染整个表格,不需要拆分表头和内容分别渲染 TableDrawer tableDrawer = TableDrawer.builder() .contentStream(contentStream) .startX(HEADER_TABLE_LOCATION_X) .startY(HEADER_TABLE_LOCATION_Y - 50) .table(fullTable) .build(); tableDrawer.draw(); }
如果之前用TableBuilder渲染失败,大概率是你没有在所有行添加完成后才调用build方法,或者是渲染的起始Y坐标设置不对(PDF的坐标系原点在左下角,Y值越小位置越靠下,如果设置的Y值过小会导致表格渲染到页面可视区域外)。
内容的提问来源于stack exchange,提问作者KikiZ
相关产品推荐
相关产品推荐

