You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:33:04