使用iText处理超页PDF表格:解决无限循环及分页、查剩余空间
iText 5.5.13.2长表格分页异常问题解决
我用iText制作了一个三列PDF表格,行数由设备传来的数据数组决定,范围1到200+行。数据行数少(单页能容纳)时一切正常,但数据量较大(40+行)时会触发Document异常,陷入无限循环。
创建表格的代码
private static PdfPTable createTableSerial(String[] serialOcr, ArrayList<java.awt.Image> serialImage) throws BadElementException { PdfPTable table = new PdfPTable(3); // t.setBorderColor(BaseColor.GRAY); // t.setPadding(4); // t.setSpacing(4); // t.setBorderWidth(1); PdfPCell c1 = new PdfPCell(new Phrase("Apoen")); c1.setHorizontalAlignment(Element.ALIGN_CENTER); table.addCell(c1); c1 = new PdfPCell(new Phrase("Serijski broj")); c1.setHorizontalAlignment(Element.ALIGN_CENTER); table.addCell(c1); c1 = new PdfPCell(new Phrase("Slika serijskog broja")); c1.setHorizontalAlignment(Element.ALIGN_CENTER); table.addCell(c1); table.setHeaderRows(serialImage.size() - 1); try { int i = 0; int j = 0; while (j < serialImage.size()) { table.addCell(serialOcr[i]); table.addCell(serialOcr[i + 1]); table.addCell(Image.getInstance(serialImage.get(j), null)); i += 2; j++; } } catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); } catch (IOException e) { throw new RuntimeException(e); } return table; }
调用方式
document.add(createTableSerial(serialOcr, serialImage));
我尝试过使用table.splitLateRows(false);,但没有效果。当前使用的iText版本为itextpdf-5.5.13.2.jar,请问:如何拆分超出单页的表格?能否检查PDF页面的剩余空间?
问题根源与解决方案
1. 无限循环的核心原因:错误的表头行数设置
你代码中的table.setHeaderRows(serialImage.size() - 1);是致命错误。setHeaderRows方法的作用是设置每页需要重复显示的表头行数,你的表格只有1行表头,应该设置为table.setHeaderRows(1);。如果设置成serialImage.size()-1,iText会认为几乎所有行都是表头,分页时会反复尝试重复表头逻辑,直接导致无限循环。先修改这行代码,这是解决问题的关键。
2. 表格自动分页的正确配置
iText 5.x的PdfPTable默认支持自动分页拆分,只要表头行数设置正确,无需额外配置。注意不要设置table.setSplitRows(false);,这个方法会禁止表格拆分。
3. 检查页面剩余空间的方法
如果需要手动判断页面剩余空间,可以通过以下代码计算:
// 获取页面总可用高度(扣除上下边距) float pageUsableHeight = document.getPageSize().getHeight() - document.topMargin() - document.bottomMargin(); // 获取当前光标距离页面底部的距离,即已用高度 float usedHeight = document.getPageSize().getHeight() - document.getVerticalPosition(false); // 计算剩余可用高度 float remainingHeight = pageUsableHeight - usedHeight;
但通常无需手动处理,表头设置正确后,iText会自动处理表格分页。
4. 额外代码优化建议
- 提前校验
serialOcr的长度是否满足2 * serialImage.size(),避免数组越界异常,比如在循环前添加:if (serialOcr == null || serialOcr.length < 2 * serialImage.size()) { throw new IllegalArgumentException("serialOcr数组长度不足"); } - 图片添加时建议设置缩放比例,避免图片过大导致单元格高度异常:
Image img = Image.getInstance(serialImage.get(j), null); img.scaleToFit(120, 80); // 根据实际需求调整尺寸 table.addCell(img);
内容的提问来源于stack exchange,提问作者Danilo Djurovic
相关产品推荐
相关产品推荐

