在Web开发中,有一个经典的功能,就是数据的导入导出。特别是数据的导出,在生产管理或者财务系统中用的非常普遍,因为这些系统经常要做一些报表打印的工作。而数据导出的格式一般是Excel 或者 PDF……
首先我们来导出Excel格式的文件吧。现在主流的操作Excel文件的开源工具有很多,用得比较多的就是Apache的POI及JExcelAPI……这里我们用Apache POI
package org.cric.util; 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 java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFCellStyle; import org.apache.poi.hssf.usermodel.HSSFClientAnchor; import org.apache.poi.hssf.usermodel.HSSFComment; import org.apache.poi.hssf.usermodel.HSSFFont; import org.apache.poi.hssf.usermodel.HSSFPatriarch; 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; /** * 利用开源组件POI3.7动态导出EXCEL文档 * @author Administrator * * @param <T> 应用泛型,代表一个符合javabean风格的类 * 注意这里为了简单起见,boolean的属性xxx的get方式为getXxx(),而不是isXxx() * byte[]表jpg格式的图片数据 */ public class ExportExcel<T> { public void exportExcel(Collection<T> dataset,OutputStream out){ this.exportExcel("测试POI导出EXCEL文档", null, dataset, out, "yyyy-MM-dd"); } public void exportExcel(String[] headers,Collection<T> dataset,OutputStream out){ this.exportExcel("测试POI导出EXCEL文档", headers, dataset, out,"yyyy-MM-dd"); } public void exportExcep(String[] headers,Collection<T> dataset,OutputStream out,String patterm){ this.exportExcel("测试POI导出EXCEL文档", headers, dataset, out, patterm); } /** * 这是一个通用的方法,利用了JAVA的反射机制,可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL的形式输出到指定IO设备上 * @param title * 表格标题名 * @param headers * 表格属性列名数组 * @param dataset * 需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。此方法支持的 * javabean属性的数据类型有基本数据类型以String,Date,byte[](图片数据) * @param out * 与输出设备关联的流对象,可以将EXCEL文档导出到本地文件或者网络中 * @param pattem * 如果有时间数据,设定输出格式。默认为"yyyy-MM-dd"; */ public void exportExcel(String title,String[] headers,Collection<T> dataset,OutputStream out,String pattem){ //声明一个工作簿 HSSFWorkbook workbook = new HSSFWorkbook(); //生成一个表格 HSSFSheet sheet = workbook.createSheet(title); //设置表格默认列宽度为15个字节 sheet.setDefaultColumnWidth(15); //生成一个样式(用于单元格) HSSFCellStyle style = workbook.createCellStyle(); style.setFillForegroundColor(HSSFColor.SKY_BLUE.index); style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); style.setBorderBottom(HSSFCellStyle.BORDER_THIN); style.setBorderLeft(HSSFCellStyle.BORDER_THIN); style.setBorderRight(HSSFCellStyle.BORDER_THIN); style.setBorderTop(HSSFCellStyle.BORDER_THIN); style.setAlignment(HSSFCellStyle.ALIGN_CENTER); //生成一个字体(用于单元格) HSSFFont font = workbook.createFont(); font.setColor(HSSFColor.VIOLET.index); font.setFontHeightInPoints((short)12); font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); //把字体应用到当前的样式 style.setFont(font); //生成并设置另一个样式 HSSFCellStyle style2 = workbook.createCellStyle(); style2.setFillForegroundColor(HSSFColor.LIGHT_YELLOW.index); style2.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); style2.setBorderBottom(HSSFCellStyle.BORDER_THIN); style2.setBorderLeft(HSSFCellStyle.BORDER_THIN); style2.setBorderRight(HSSFCellStyle.BORDER_THIN); style2.setBorderTop(HSSFCellStyle.BORDER_THIN); style2.setAlignment(HSSFCellStyle.ALIGN_CENTER); style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); //生成另一个字体 HSSFFont font2 = workbook.createFont(); font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL); //把字体应用到当前的样式 style2.setFont(font2); //声明一个画图的顶级管理器 HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); //定义注释的大小和位置,详见文档 HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0,0,0,0,(short)4,2,(short)6,5)); //设置注释内容 comment.setString(new HSSFRichTextString("可以在POI中添加注释!")); //设置注释作者,当鼠标移动单单元格上是可以在状态栏中看到该内容。 comment.setAuthor("wuhaidong"); //产生表格标题行 HSSFRow row = sheet.createRow(0); for(int i = 0; i < headers.length; i++){ HSSFCell cell = row.createCell(i); cell.setCellStyle(style);//设置单元格样式(包含字体) 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(style2); Field field = fields[i]; String fieldName = field.getName(); String getMethodName = "get"+fieldName.substring(0, 1).toUpperCase()+fieldName.substring(1); Class tCls = t.getClass(); try { Method getMethod = tCls.getMethod(getMethodName, new Class[]{}); Object value = getMethod.invoke(t, new Object[]{}); // 判断值的类型后进行强制类型转换 String textValue = null; /*if(value instanceof Integer){ Integer intValue = (Integer)value; cell.setCellValue(intValue); }else if(value instanceof Float){ Float floatValue = (Float)value; cell.setCellValue(floatValue); }else if(value instanceof Double){ Double doubleValue = (Double)value; cell.setCellValue(doubleValue); }else if(value instanceof Long){ Long longValue = (Long)value; cell.setCellValue(longValue); }else */ if(value instanceof Boolean){ boolean booleanValue = (Boolean)value; textValue = "男"; if(!booleanValue){ textValue = "女"; } cell.setCellValue(textValue); }else if(value instanceof Date){ Date date = (Date)value; SimpleDateFormat sdf = new SimpleDateFormat(pattem); textValue = sdf.format(date); cell.setCellValue(textValue); }else if(value instanceof byte[]){ //有图片时,设置行高为60px; row.setHeightInPoints(60); //设置有图片所在列宽度为80px,注意这里单位的一个换算 sheet.setColumnWidth(i, (short)(35.7*80)); //sheet.autoSizeColumn(i); byte[] bsValue = (byte[])value; HSSFClientAnchor anchor = new HSSFClientAnchor(0,0,1023,55,(short)6,index,(short)6,index); anchor.setAnchorType(2); patriarch.createPicture(anchor,workbook.addPicture(bsValue, HSSFWorkbook.PICTURE_TYPE_JPEG)); }else{ //其它数据类型都当做字符串简单处理 textValue = value.toString(); } //如果不是图片数据,就利用正则表达式判断textValue是否全部由数字组成 if(textValue != null){ Pattern p = Pattern.compile("^\\d+(\\.\\d+)?$"); Matcher matcher = p.matcher(textValue); if(matcher.matches()){ //是数字当作double处理 cell.setCellValue(Double.parseDouble(textValue)); }else{ HSSFRichTextString richString = new HSSFRichTextString(textValue); HSSFFont font3 = workbook.createFont(); font3.setColor(HSSFColor.BLUE.index); richString.applyFont(font3); cell.setCellValue(richString); } } } 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(); }finally{ //关闭资源 } } } try { workbook.write(out); } catch (IOException e) { e.printStackTrace(); } } }
package org.cric.util; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.swing.JOptionPane; import org.leno.export.util.Student; public class ExportExcelTest { public static void main(String[] args) { ExportExcel<Student> exportExcel = new ExportExcel<Student>(); String[] headers = new String[]{"学好","姓名","年龄","性别","出生日期"}; Student stu = new Student(1000,"小三",23,true, new Date()); Student stu2 = new Student(1001,"李四",22,false,new Date()); Student stu3 = new Student(1002,"老张",24,true,new Date()); Student stu4 = new Student(1003,"王五",22,true,new Date()); List<Student> studentList = new ArrayList<Student>(); studentList.add(stu); studentList.add(stu2); studentList.add(stu3); studentList.add(stu4); FileOutputStream out = null; try { out = new FileOutputStream("E:\\报表.xls"); exportExcel.exportExcep(headers, studentList, out, "yyyy-MM-dd"); JOptionPane.showMessageDialog(null, "导出成功"); System.out.println("EXCEL导出成功!"); } catch (FileNotFoundException e) { e.printStackTrace(); }finally{ if(null != out){ try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } }