报表是需要联合查询的数据集,一般不会有对应的POJO类,如果手动封装字段那就太低效了.泛型和反射技术可以将报表数据通过几行代码写到VO集合中.
说明:
后台查询的结果集合: List
查看BeanUtils.populate()的源代码
public static void populate(Object bean, Map properties)
throws IllegalAccessException, InvocationTargetException {
BeanUtilsBean.getInstance().populate(bean, properties);
}
BeanUtilsBean中的populate()实现
public void populate(Object bean, Map properties)
throws IllegalAccessException, InvocationTargetException {
// Do nothing unless both arguments have been specified
if ((bean == null) || (properties == null)) {
return;
}
if (log.isDebugEnabled()) {
log.debug("BeanUtils.populate(" + bean + ", " +
properties + ")");
}
// Loop through the property name/value pairs to be set
Iterator entries = properties.entrySet().iterator();
while (entries.hasNext()) {
// Identify the property name and value(s) to be assigned
Map.Entry entry = (Map.Entry)entries.next();
String name = (String) entry.getKey();
if (name == null) {
continue;
}
// Perform the assignment for this property
setProperty(bean, name, entry.getValue());
}
}
##########setProperty() 将目标值放入bean的name属性中
public void setProperty(Object bean, String name, Object value)
throws IllegalAccessException, InvocationTargetException {
// 写日志
.....
// 解析表达式来获取实际的bean
.....
// 计算出属性的数据类型
.....
// 将指定的值转换为属性所需的类型
.....
// 访问setter访问器设定值
try {
getPropertyUtils().setProperty(target, name, newValue);
} catch (NoSuchMethodException e) {
throw new InvocationTargetException
(e, "Cannot set " + propName);
}
}
HSSFWorkbook对象是apache poi项目包里面的Excel顶级对象,我们的原材料包含:
属性 文件名 sheet标题 表头Map集合 数据集合 方法 写入到Excel输出到response中
public class Exceltools {
private String fname;// 文件名称
private String sName;// sheet标题
private Map ziDuan;// 字段名称 ziDuan.put("0_fjh","房间号");属性前边的数字代表字段的先后顺序。
private List listData;// 数据集
private HttpServletResponse response;
public Exceltools(String fileName, String sheetName,
Map ziDuan, List listData,
HttpServletResponse response) {
this.fname = fileName;
this.sName = sheetName;
this.ziDuan = ziDuan;
this.listData = listData;
this.response = response;
}
/**
* 将对象集合导出到Excel回客户端
* */
public void writeToExcel() {
Object[] keys = ziDuan.keySet().toArray();
String[] ziDuanKeys = new String[keys.length];
for (int k = 0; k < keys.length; k++) {
String temp = keys[k].toString();
int xuHao = Integer
.valueOf(temp.substring(0, temp.indexOf("_", 0)));
ziDuanKeys[xuHao] = temp.substring(temp.indexOf("_", 0) + 1);
}
OutputStream out = null;
try {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet(sName);
HSSFRow row = sheet.createRow(0);
for (int j = 0; j < ziDuanKeys.length; j++) {
HSSFCell cell = row.createCell(j);
// sheet表头,无论如何都要先打印表头
sheet.setColumnWidth(j, 6000);
cell.setCellValue(new HSSFRichTextString(ziDuan.get(j + "_"
+ ziDuanKeys[j])));
}
for (int i = 0; i < listData.size(); i++) {
HSSFRow row2 = sheet.createRow(i + 1);
T obj = listData.get(i);
for (int j = 0; j < ziDuanKeys.length; j++) {
HSSFCell cell = row2.createCell(j);
// 内容
String ziDuanName = (String) ziDuanKeys[j];
ziDuanName = ziDuanName.replaceFirst(
ziDuanName.substring(0, 1),
ziDuanName.substring(0, 1).toUpperCase());
ziDuanName = "get" + ziDuanName;
Class clazz = Class.forName(obj.getClass().getName());
Method[] methods = clazz.getMethods();
Pattern pattern = Pattern.compile(ziDuanName);
Matcher mat = null;
for (Method m : methods) {
mat = pattern.matcher(m.getName());
if (mat.find()) {
Object shuXing = m.invoke(obj, null);
if (shuXing != null) {
cell.setCellValue(shuXing.toString());// 这里可以做数据格式处理
} else {
cell.setCellValue("");
}
break;
}
}
}
}
response.setContentType("application/vnd.ms-excel;charset = utf-8");
response.setHeader("Content-disposition", "attachment;filename="
+ new String(sName.getBytes("GBK"), "ISO-8859-1")+".xlsx");
out = response.getOutputStream();
wb.write(out);// 写入File
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
这样一个数据报表的导出就完成了.
除了使用反射,泛型等技术外,还用到了正则表达式的匹配.如果有不明白的地方,欢迎一起探讨,交换思想.QQ:185748383