最近项目上需要用到数据导出,研究对比了apache的poi导出和一位大师的jxl的api!最后写出了两个实现!
总体发现,jxl的数据导出性能比较好,当然大名鼎鼎的apache的功能强大,大家各自看看自己需要用到那个!
下面这两个都是我写的工具,直接拿去就可以用的,只是需要自己添加jar包!自行下载了!
这个工具放在项目里面,需要导出的地方就可以直接调用即可!
我测试的是:
用下面程序导出数据30000条,apach poi 报虚拟机内存不足 , jxl顺利导出!
好了,代码如下:
1. apache的poi
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.util.CellRangeAddress;
/**
*
* @author chen-zhenxing
*
* @param <T> 需要导出的实体Bean类名
*/
public class ExportExcelByPOI<T> {
/**
* 日期格式,例如:2012-10-10
*/
public static final String DATE = "yyyy-MM-dd";
/**
* 日期时间格式,例如:2012-10-10 16:25:31
*/
public static final String DATE_TIME = "yyyy-MM-dd hh:mm:ss";
/**
* 时间格式,例如:16:25:31
*/
public static final String TIME = "hh:mm:ss";
/**
* 日期时间星期格式,例如:2012-10-10 16:25:31 星期三
*/
public static final String DATE_TIME_WEEK = "yyyy-MM-dd hh:mm:ss EEE";
/**
* 默认宽度
* @param length 数组维数
* @return 返回默认宽度数组
*/
private int[] getWidths(int length){
int[] widths = new int[length];
for(int i=0;i<widths.length;i++){
widths[i] = 256*15*2;
}
return widths;
}
/**
* 宽度数组转换,因为设置的数字宽度与excle中的宽度需要比例计算
* @param widths 数组宽度数组
* @return 转换后的数组宽度数组
*/
private void changeWidths(int[] widths){
for(int i=0;i<widths.length;i++){
widths[i] = widths[i]*2*256;
}
}
/**
* 通过反射将集合数据中的实体Bean生成Excel形式输出到输出流
* @param title 表格sheet名称
* @param headers 表格列名数组
* @param dataset 数据实体Bean集合
* @param out 输出流
*/
public void export(String title,String[] headers,Collection<T> dataset,OutputStream out){
excleExport(title,getWidths(headers.length),headers,dataset,out,DATE_TIME);
}
/**
* 通过反射将集合数据中的实体Bean生成Excel形式输出到输出流
* @param title 表格sheet名称
* @param headers 表格列名数组
* @param dataset 数据实体Bean集合
* @param out 输出流
* @param dataPattern 日期格式化字符串
*/
public void export(String title,String[] headers,Collection<T> dataset,OutputStream out,String dataPattern){
excleExport(title,getWidths(headers.length),headers,dataset,out,dataPattern);
}
/**
* 通过反射将集合数据中的实体Bean生成Excel形式输出到输出流
* @param title 表格sheet名称
* @param widths 表格各列宽度
* @param headers 表格列名数组
* @param dataset 数据实体Bean集合
* @param out 输出流
*/
public void export(String title,int[] widths,String[] headers,Collection<T> dataset,OutputStream out){
changeWidths(widths);
excleExport(title,widths,headers,dataset,out,DATE_TIME);
}
/**
* 通过反射将集合数据中的实体Bean生成Excel形式输出到输出流
* @param title 表格sheet名称
* @param widths 表格各列宽度
* @param headers 表格列名数组
* @param dataset 数据实体Bean集合
* @param out 输出流
* @param dataParttern 日期格式字符串,推荐采用本类提供静态变量
*/
public void export(String title,int[] widths,String[] headers,Collection<T> dataset,OutputStream out,String dataParttern){
changeWidths(widths);
excleExport(title, widths, headers, dataset, out, dataParttern);
}
/**
* 通过反射将集合数据中的实体Bean生成Excel形式输出到输出流
* @param title 表格sheet名称
* @param widths 表格各列宽度
* @param headers 表格列名数组
* @param dataset 数据实体Bean集合
* @param out 输出流
* @param dataParttern 日期格式字符串,推荐采用本类提供静态变量
*/
private void excleExport(String title,int[] widths,String[] headers,Collection<T> dataset,OutputStream out,String dataParttern){
// 声明一个工作薄
HSSFWorkbook workbook = new HSSFWorkbook();
// 生成一个表格
HSSFSheet sheet = workbook.createSheet(title);
// 设置表格默认列宽度 width 个字节
for (int i = 0; i < headers.length; i++){
sheet.setColumnWidth(i,widths[i]);
}
// 生成一个样式
HSSFCellStyle style_title = workbook.createCellStyle();
// 设置这些样式
style_title.setFillForegroundColor(HSSFColor.YELLOW.index);
style_title.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style_title.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style_title.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style_title.setBorderRight(HSSFCellStyle.BORDER_THIN);
style_title.setBorderTop(HSSFCellStyle.BORDER_THIN);
style_title.setAlignment(HSSFCellStyle.ALIGN_CENTER);
// 生成一个字体
HSSFFont font_title = workbook.createFont();
font_title.setColor(HSSFFont.COLOR_NORMAL);
font_title.setFontHeightInPoints((short)12);
font_title.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
// 将字体应用到样式中
style_title.setFont(font_title);
// 生成并设置另外一个样式
HSSFCellStyle style_content = workbook.createCellStyle();
style_content.setFillForegroundColor(HSSFColor.WHITE.index);
style_content.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style_content.setBorderBottom(HSSFCellStyle.BORDER_THIN);
style_content.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style_content.setBorderRight(HSSFCellStyle.BORDER_THIN);
style_content.setBorderTop(HSSFCellStyle.BORDER_THIN);
style_content.setAlignment(HSSFCellStyle.ALIGN_CENTER);
style_content.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
// 生成另一个字体
HSSFFont font_content = workbook.createFont();
font_content.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL);
// 把字体应用到当前的样式
style_content.setFont(font_content);
// 产生表格标题行
HSSFRow row = sheet.createRow(0);
row.setHeight((short)400);
for (int i = 0; i < headers.length; i++) {
HSSFCell cell = row.createCell(i);
cell.setCellStyle(style_title);
HSSFRichTextString text = new HSSFRichTextString(headers[i]);
cell.setCellValue(text);
}
// 遍历集合数据,产生数据行
Iterator<T> it = dataset.iterator();
int index = 0;
while(it.hasNext()){
index++;
row = sheet.createRow(index);
T t = (T)it.next();
// 利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值
Field[] fields = t.getClass().getDeclaredFields();
for(int i=0;i<fields.length;i++){
HSSFCell cell = row.createCell(i);
cell.setCellStyle(style_content);
Field field = fields[i];
String fieldName = field.getName();
String getMethodName = "get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
try {
Class<?> clazz = t.getClass();
Method getMethod = clazz.getMethod(getMethodName, new Class[]{});
Object value = getMethod.invoke(t,new Object[]{});
if(value instanceof Date){
Date date = (Date)value;
cell.setCellValue(new SimpleDateFormat(dataParttern).format(date));
}else{
cell.setCellValue(String.valueOf(value));
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
// 增加版权信息
row = sheet.createRow(index+2);
HSSFCell cell = row.createCell(headers.length-2);
cell.setCellValue("数据来源:中缆在线[http://www.dianlan.cn]");
cell = row.createCell(headers.length-1);
sheet.addMergedRegion(new CellRangeAddress(index+2,index+2, headers.length-2,headers.length-1));
row = sheet.createRow(index+3);
cell = row.createCell(headers.length-2);
cell.setCellValue("导出时间:"+new SimpleDateFormat("yyyy-MM-ss hh:MM:ss").format(new Date()));
cell = row.createCell(headers.length-1);
sheet.addMergedRegion(new CellRangeAddress(index+3,index+3, headers.length-2,headers.length-1));
try {
workbook.write(out);
} catch (IOException e) {
e.printStackTrace();
}
}
}
2. jxl
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import jxl.Workbook;
import jxl.format.Alignment;
import jxl.format.Border;
import jxl.format.BorderLineStyle;
import jxl.format.Colour;
import jxl.write.Label;
import jxl.write.WritableCellFormat;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
/**
* <pre>
* 采用反射机制将实体bean集合数据导出为excel形式
* 本类只有一个方法可以调用,请注意参数传递
* </pre>
* @author chen-zhenxing 2012年10月11日18:02:27
*
* @param <T> 需要导出的实体Bean
*/
public class ExportExcelByJXL<T> {
/**
* 日期格式,例如:2012-10-10
*/
public static final String DATE = "yyyy-MM-dd";
/**
* 日期时间格式,例如:2012-10-10 16:25:31
*/
public static final String DATE_TIME = "yyyy-MM-dd hh:mm:ss";
/**
* 时间格式,例如:16:25:31
*/
public static final String TIME = "hh:mm:ss";
/**
* 日期时间星期格式,例如:2012-10-10 16:25:31 星期三
*/
public static final String DATE_TIME_WEEK = "yyyy-MM-dd hh:mm:ss EEE";
/**
* 采用反射机制将实体bean集合数据导出为excel形式
* @param title 表格标题,将显示在sheet的名称处
* @param widths 列宽数组
* @param headers 列标题数组
* @param dataset 实体bean数据集合
* @param authors 版权信息数组
* @param out 输出流
* @param dataPattern 日期格式化字符串
*/
public void export(String title,int[] widths,String[] headers,Collection<T> dataset,String[] authors,OutputStream out,String dataPattern){
// 设置行标
int cellIndex = 0;
// 关联表格内容到输出流
WritableWorkbook workbook = null;
// 创建一个sheet
WritableSheet sheet = null;
// 设置标题样式
WritableCellFormat title_format = null;
// 设置内容样式
WritableCellFormat content_format = null;
// 单元格
Label label = null;
try {
workbook = Workbook.createWorkbook(out);
sheet = workbook.createSheet(title,0);
// 设置标题样式
title_format = new WritableCellFormat();
title_format.setBackground(Colour.YELLOW2);
title_format.setAlignment(Alignment.CENTRE);
title_format.setBorder(Border.ALL, BorderLineStyle.THIN);
// 设置列宽
for(int i=0;i<widths.length;i++){
sheet.setColumnView(i,widths[i]);
}
// 插入标题栏目
for(int i=0;i<headers.length;i++){
label = new Label(i,cellIndex,headers[i],title_format);
sheet.addCell(label);
}
// 设置内容样式
content_format = new WritableCellFormat();
content_format.setBackground(Colour.WHITE);
content_format.setAlignment(Alignment.CENTRE);
content_format.setBorder(Border.ALL,BorderLineStyle.THIN);
// 利用反射插入数据
Iterator<T> its = dataset.iterator();
String fieldName = "";
String methodName = "";
Object value = null;
while(its.hasNext()){
// 行标下移
cellIndex++;
T t = its.next();
Field[] fields = t.getClass().getDeclaredFields();
for(int i=0;i<fields.length;i++){
fieldName = fields[i].getName();
methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
value = t.getClass().getMethod(methodName, new Class[]{}).invoke(t,new Object[]{});
// 对日期数据进行处理
if(value instanceof Date){
label = new Label(i,cellIndex,new SimpleDateFormat(dataPattern).format(value),content_format);
}else{
// 其他数据用字符串对待
label = new Label(i,cellIndex,String.valueOf(value),content_format);
}
sheet.addCell(label);
}
}
cellIndex++;
// 设置版权信息和导出时间
for(int i=1;i<=authors.length;i++){
sheet.mergeCells(0,cellIndex+i, headers.length-1, cellIndex+i);
sheet.addCell(new Label(0,cellIndex+i,authors[i-1]));
}
workbook.write();
workbook.close();
} catch (IOException e) {
e.printStackTrace();
} catch (WriteException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}