如何用iText创建带重复表头的左右分栏6列表格?
实现带重复双表头、左右分栏填充的iText表格
嗨,我来帮你搞定这个iText表格的需求!根据你的描述,要做一个带重复双表头的6列表格,先填满左三列再填右三列,我给你梳理一套完整的实现方案:
1. 先理清楚数据拆分逻辑
首先我们得把从数据库拿到的按日期排序的数据,拆成左三列数据集和右三列数据集。核心思路是:先算出需要多少行,左三列先放前N行数据,剩下的放在右三列,要是数据总数是奇数,右三列最后一行就留空。
比如总共有7条数据,左三列放前4条(占4行),右三列放后3条(占前3行),第4行的右三列空着。代码里可以这么算:
List<YourDataClass> dataList = ...; // 你的数据库数据列表 int totalData = dataList.size(); int rowCount = (totalData + 1) / 2; // 向上取整,保证左列能装下所有数据的一半以上 List<YourDataClass> leftData = new ArrayList<>(); List<YourDataClass> rightData = new ArrayList<>(); for (int i = 0; i < totalData; i++) { if (i < rowCount) { leftData.add(dataList.get(i)); } else { rightData.add(dataList.get(i)); } }
2. 创建带重复表头的6列表格
iText里要让表头每页重复,关键是用setHeaderRows()方法标记表头行。我们的表格是6列,左右三列用相同的表头,所以要把表头单元格加两次:
// 创建6列的表格,占满页面宽度 PdfPTable table = new PdfPTable(6); table.setWidthPercentage(100); // 设置每列宽度,左右三列宽度一致 float[] columnWidths = {1f, 1f, 1f, 1f, 1f, 1f}; table.setWidths(columnWidths); // 构建表头单元格,加个灰色背景更清晰 PdfPCell header1 = new PdfPCell(new Phrase("表头1")); header1.setBackgroundColor(BaseColor.LIGHT_GRAY); header1.setPadding(5); // 加内边距更美观 PdfPCell header2 = new PdfPCell(new Phrase("表头2")); header2.setBackgroundColor(BaseColor.LIGHT_GRAY); header2.setPadding(5); PdfPCell header3 = new PdfPCell(new Phrase("表头3")); header3.setBackgroundColor(BaseColor.LIGHT_GRAY); header3.setPadding(5); // 添加表头行:左三列表头 + 右三列表头 table.addCell(header1); table.addCell(header2); table.addCell(header3); table.addCell(header1); // 重复表头 table.addCell(header2); table.addCell(header3); // 标记这一行是表头,每页都会自动重复 table.setHeaderRows(1);
3. 填充数据到表格里
接下来循环rowCount次,每次填充左三列的一行数据,再填充右三列的一行数据(如果有数据的话):
for (int i = 0; i < rowCount; i++) { // 填充左三列数据 YourDataClass leftItem = leftData.get(i); table.addCell(new Phrase(leftItem.getField1())); table.addCell(new Phrase(leftItem.getField2())); table.addCell(new Phrase(leftItem.getField3())); // 填充右三列数据,没有数据就放空单元格 if (i < rightData.size()) { YourDataClass rightItem = rightData.get(i); table.addCell(new Phrase(rightItem.getField1())); table.addCell(new Phrase(rightItem.getField2())); table.addCell(new Phrase(rightItem.getField3())); } else { table.addCell(new Phrase("")); table.addCell(new Phrase("")); table.addCell(new Phrase("")); } }
4. 完整可运行示例
这里给你一个完整的示例代码,包含模拟数据和导出PDF的逻辑:
import com.itextpdf.text.*; import com.itextpdf.text.pdf.*; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.List; public class DoubleColumnTableDemo { public static void main(String[] args) throws Exception { // 模拟从数据库获取的按日期排序的数据 List<DataRecord> dataList = new ArrayList<>(); for (int i = 1; i <= 7; i++) { dataList.add(new DataRecord("2024-05-" + i, "记录内容" + i, "数值" + i)); } // 初始化PDF文档 Document document = new Document(); PdfWriter.getInstance(document, new FileOutputStream("double_column_table.pdf")); document.open(); // 创建表格 PdfPTable table = new PdfPTable(6); table.setWidthPercentage(100); float[] widths = {1f, 1f, 1f, 1f, 1f, 1f}; table.setWidths(widths); // 创建表头 PdfPCell dateHeader = new PdfPCell(new Phrase("日期")); dateHeader.setBackgroundColor(BaseColor.LIGHT_GRAY); dateHeader.setPadding(5); PdfPCell contentHeader = new PdfPCell(new Phrase("内容")); contentHeader.setBackgroundColor(BaseColor.LIGHT_GRAY); contentHeader.setPadding(5); PdfPCell valueHeader = new PdfPCell(new Phrase("数值")); valueHeader.setBackgroundColor(BaseColor.LIGHT_GRAY); valueHeader.setPadding(5); // 添加表头行 table.addCell(dateHeader); table.addCell(contentHeader); table.addCell(valueHeader); table.addCell(dateHeader); table.addCell(contentHeader); table.addCell(valueHeader); // 设置表头重复 table.setHeaderRows(1); // 拆分数据 int total = dataList.size(); int rowCount = (total + 1) / 2; List<DataRecord> leftData = new ArrayList<>(); List<DataRecord> rightData = new ArrayList<>(); for (int i = 0; i < total; i++) { if (i < rowCount) { leftData.add(dataList.get(i)); } else { rightData.add(dataList.get(i)); } } // 填充数据 for (int i = 0; i < rowCount; i++) { // 左三列 DataRecord left = leftData.get(i); table.addCell(new Phrase(left.getDate())); table.addCell(new Phrase(left.getContent())); table.addCell(new Phrase(left.getValue())); // 右三列 if (i < rightData.size()) { DataRecord right = rightData.get(i); table.addCell(new Phrase(right.getDate())); table.addCell(new Phrase(right.getContent())); table.addCell(new Phrase(right.getValue())); } else { table.addCell(new Phrase("")); table.addCell(new Phrase("")); table.addCell(new Phrase("")); } } // 将表格加入文档 document.add(table); document.close(); System.out.println("PDF生成完成!"); } // 模拟你的数据实体类 static class DataRecord { private String date; private String content; private String value; public DataRecord(String date, String content, String value) { this.date = date; this.content = content; this.value = value; } public String getDate() { return date; } public String getContent() { return content; } public String getValue() { return value; } } }
一些注意事项
- 确保你引入了正确的iText依赖,比如Maven的依赖配置:
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.13.3</version> </dependency>
- 如果使用的是iText 7,API会有一些变化,比如用
PdfTable代替PdfPTable,Cell代替PdfPCell,但核心的拆分数据和重复表头的逻辑是完全一致的。 - 你可以根据附图的样式,调整列宽、字体、单元格对齐方式、边框等,让表格更符合需求。
内容的提问来源于stack exchange,提问作者Sameer
相关产品推荐
相关产品推荐

