大多数情况下,FineReport直接在设计器里使用“数据集查询”,直接写SQL就能满足报表要求,但对于一些复杂的报表,有时候SQL处理并不方便,这时可以把查询结果在应用层做一些预处理后,再传递给报表,即所谓的“程序数据集”,FineReport的帮助文档上给了一个示例:
1 package com.fr.data; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.ResultSet; 6 import java.sql.ResultSetMetaData; 7 import java.sql.Statement; 8 import java.util.ArrayList; 9 import com.fr.base.FRContext; 10 import com.fr.data.AbstractTableData; 11 import com.fr.base.Parameter; 12 13 public class ParamTableDataDemo extends AbstractTableData { 14 // 列名数组,保存程序数据集所有列名 15 private String[] columnNames = null; 16 // 定义程序数据集的列数量 17 private int columnNum = 10; 18 // 保存查询表的实际列数量 19 private int colNum = 0; 20 // 保存查询得到列值 21 private ArrayList valueList = null; 22 23 // 构造函数,定义表结构,该表有10个数据列,列名为column#0,column#1,。。。。。。column#9 24 public ParamTableDataDemo() { 25 // 定义tableName参数 26 this.parameters = new Parameter[] { new Parameter("tableName") }; 27 // 定义程序数据集列名 28 columnNames = new String[columnNum]; 29 for (int i = 0; i < columnNum; i++) { 30 columnNames[i] = "column#" + String.valueOf(i); 31 } 32 } 33 34 // 实现其他四个方法 35 public int getColumnCount() { 36 return columnNum; 37 } 38 39 public String getColumnName(int columnIndex) { 40 return columnNames[columnIndex]; 41 } 42 43 public int getRowCount() { 44 init(); 45 return valueList.size(); 46 } 47 48 public Object getValueAt(int rowIndex, int columnIndex) { 49 init(); 50 if (columnIndex >= colNum) { 51 return null; 52 } 53 return ((Object[]) valueList.get(rowIndex))[columnIndex]; 54 } 55 56 // 准备数据 57 public void init() { 58 // 确保只被执行一次 59 if (valueList != null) { 60 return; 61 } 62 // 保存得到的数据库表名 63 String tableName = parameters[0].getValue().toString(); 64 // 构造SQL语句,并打印出来 65 String sql = "select * from " + tableName + ";"; 66 FRContext.getLogger().info("Query SQL of ParamTableDataDemo: \n" + sql); 67 // 保存得到的结果集 68 valueList = new ArrayList(); 69 // 下面开始建立数据库连接,按照刚才的SQL语句进行查询 70 Connection conn = this.getConnection(); 71 try { 72 Statement stmt = conn.createStatement(); 73 ResultSet rs = stmt.executeQuery(sql); 74 // 获得记录的详细信息,然后获得总列数 75 ResultSetMetaData rsmd = rs.getMetaData(); 76 colNum = rsmd.getColumnCount(); 77 // 用对象保存数据 78 Object[] objArray = null; 79 while (rs.next()) { 80 objArray = new Object[colNum]; 81 for (int i = 0; i < colNum; i++) { 82 objArray[i] = rs.getObject(i + 1); 83 } 84 // 在valueList中加入这一行数据 85 valueList.add(objArray); 86 } 87 // 释放数据库资源 88 rs.close(); 89 stmt.close(); 90 conn.close(); 91 // 打印一共取到的数据行数量 92 FRContext.getLogger().info( 93 "Query SQL of ParamTableDataDemo: \n" + valueList.size() 94 + " rows selected"); 95 } catch (Exception e) { 96 e.printStackTrace(); 97 } 98 } 99 100 // 获取数据库连接 driverName和 url 可以换成您需要的 101 public Connection getConnection() { 102 String driverName = "sun.jdbc.odbc.JdbcOdbcDriver"; 103 String url = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=D:\\FineReport_7.0\\WebReport\\FRDemo.mdb"; 104 String username = ""; 105 String password = ""; 106 Connection con = null; 107 try { 108 Class.forName(driverName); 109 con = DriverManager.getConnection(url, username, password); 110 } catch (Exception e) { 111 e.printStackTrace(); 112 return null; 113 } 114 return con; 115 } 116 117 // 释放一些资源,因为可能会有重复调用,所以需释放valueList,将上次查询的结果释放掉 118 public void release() throws Exception { 119 super.release(); 120 this.valueList = null; 121 } 122 }