業務系統常需導出複雜報表,本文基於 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. 寫入文檔並關閉流
}
// filedir.properties
pdfPath=E:/appDataPdf
// GetFilePlace 讀取工具
public String getFileDirFromProperties(String key) {
Properties props = loadProperties("META-INF/filedir.properties");
return props.getProperty(key);
}
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;
}
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;
}
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);
}
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 策略類,支援條件格式化