首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java iText 動態生成 PDF 表格完整實戰:泛型表頭、反射數據綁定、多級目錄存儲

     編輯:Java 相關知識

Java 動態導出 PDF 表格工程化實現指南

業務系統常需導出複雜報表,本文基於 iText 2.x/5.x 實現通用 PDF 表格生成器,支援泛型表頭定義、反射自動綁定實體屬性、按日期分目錄存儲、毫秒級 UUID 文件名防衝突。

核心架構設計

// 統一入口
public <T> String exportPdf(String[] headers, List<T> dataList) {
    // 1. 解析存儲路徑 (properties 配置)
    // 2. 生成日期目錄 (yyyyMMdd)
    // 3. 生成唯一文件名 (yyyyMMddHHmmssSS-UUID.pdf)
    // 4. 初始化 Document & PdfWriter
    // 5. 構建表格: 表頭 -> 數據行 (反射調用 getter)
    // 6. 寫入文檔並關閉流
}

關鍵模塊實現

1. 配置驅動的存儲路徑

// filedir.properties
pdfPath=E:/appDataPdf

// GetFilePlace 讀取工具
public String getFileDirFromProperties(String key) {
    Properties props = loadProperties("META-INF/filedir.properties");
    return props.getProperty(key);
}

2. 日期分級目錄生成

public String getFold(String rootPath) {
    String dateDir = new SimpleDateFormat("yyyyMMdd").format(new Date());
    String fullPath = rootPath + File.separator + dateDir;
    new File(fullPath).mkdirs();
    return fullPath;
}

3. 唯一文件名生成 (毫秒 + UUID)

public String generateFileName(String dir, String ext) {
    String timestamp = new SimpleDateFormat("yyyyMMddHHmmssSS").format(new Date());
    String uuid = UUID.randomUUID().toString();
    return dir + File.separator + timestamp + "-" + uuid + "." + ext;
}

4. 通用表格構建器 (iText 核心)

public <T> void generatePDF(String[] headers, List<T> list, int colNum) {
    PdfPTable table = createTable(colNum);
    table.addCell(createCell("報表標題", titleFont, Element.ALIGN_LEFT, colNum, false));
    
    // 表頭
    for (String h : headers) table.addCell(createCell(h, headerFont));
    
    // 數據行 - 反射動態綁定
    Class<?> clazz = list.get(0).getClass();
    for (T t : list) {
        for (int j = 0; j < colNum; j++) {
            String fieldName = headers[j];
            String getter = "get" + Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
            try {
                Method m = clazz.getMethod(getter);
                Object val = m.invoke(t);
                table.addCell(createCell(val != null ? val.toString() : "", dataFont));
            } catch (Exception e) {
                table.addCell(createCell("", dataFont)); // 容錯
            }
        }
    }
    document.add(table);
}

5. 中文字體解決方案

static {
    BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
    titleFont = new Font(bfChinese, 12, Font.BOLD);
    headerFont = new Font(bfChinese, 10, Font.BOLD);
    dataFont = new Font(bfChinese, 9, Font.NORMAL);
}

注意:iText 5+ 需 itext-asian 依賴;生產環境建議嵌入字體 (BaseFont.EMBEDDED) 確保跨平台顯示一致。

實體類規範 (約定優於配置)

public class User {
    private String name;    // 表頭 "name" -> getName()
    private int age;        // 表頭 "age" -> getAge()
    // 必須提供標準 Getter,字段名與表頭對應
}

測試驗證

String[] headers = {"name", "sex", "address", "height", "age", "note"};
List<User> data = Arrays.asList(
    new User("張三", "男", "北京", 1.75f, 25, "備註1"),
    new User("李四", "女", "上海", 1.62f, 28, "備註2")
);
String path = new CreatePdf().generatePDFs(headers, data);
// 輸出: E:/appDataPdf/20240115/20240115143025123-abc123.pdf

生產級優化清單

  • 大數據分頁:document.newPage() 配合 table.setHeaderRows(1) 重複表頭
  • 列寬自適應:預計算內容寬度或使用 PdfPTable(float[] widths)
  • 樣式模板化:抽離 CellStyle 策略類,支援條件格式化
  • 異步導出:大報表放入任務隊列,前端輪詢下載鏈接
  • 升級 iText 7/8:模塊化架構、更好記憶體控制、PDF/UA 無障礙支援
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved