POI之EXCEL导出工具--PoiExportUtil入门篇--(三)
转载自:https://blog.csdn.net/Jack__Frost/article/details/77623052
本篇章先做个简单的万能POI之EXCEL导出工具(博主已经抽象成库,请于文末前去使用),后面再做个优化分页的万能POI之EXCEL导出工具。
文章结构:(1)面向JavaBean的导出工具;(2)面向List-Map结构的导出工具。
大家阅读了前篇就知道Excel报表导出之JSP方式就是这么简单了,查出数据直接对到jsp处理,样式也可以在制作excel模板时自定义,相当简单。但是我们要想当要导出大量数据的时候呢??难道我们也这样实时导出??这样一个正常系统而且在大量人使用的时候,对于系统的负载会非常非常高的,所以前篇我也给出了另一种方式:Excel报表导出之上传文件流方式。在这样的方式下,如何做出一个公用的适应各种情况的设计,这就是往后几篇文章要探讨的。
一、面向JavaBean的导出工具:
(一)设计的关键:
(1)兼容普通JavaBean;
(2)接口方法易用性;
(3)导出数据准确性;
(4)扩展性。
(二)基于POI抽象的关键步骤:
(1)设置表格标题
(2)设置标题栏
(3)设置内容栏(为了精确比对,需要给出标题栏对应的字段—DTO类(普通javabean)的属性)
(4)导出写入到流对象
(三)核心代码与demo:
准备实体:(一个普通的JavaBean)
1 package com.fuzhu.model; 2 3 /** 4 * Created by 符柱成 on 2017/8/24. 5 */ 6 public class Student { 7 private int id; 8 private String name; 9 private String sex; 10 11 public Student(int id, String name, String sex) { 12 this.id = id; 13 this.name = name; 14 this.sex = sex; 15 } 16 17 public int getId() { 18 return id; 19 } 20 21 public void setId(int id) { 22 this.id = id; 23 } 24 25 public String getName() { 26 return name; 27 } 28 29 public void setName(String name) { 30 this.name = name; 31 } 32 33 public String getSex() { 34 return sex; 35 } 36 37 public void setSex(String sex) { 38 this.sex = sex; 39 } 40 }
工具代码:
1 package com.fuzhu.utils; 2 3 /** 4 * Created by 符柱成 on 2017/8/23. 5 */ 6 7 import java.io.FileNotFoundException; 8 import java.io.FileOutputStream; 9 import java.io.IOException; 10 import java.lang.reflect.Field; 11 import java.lang.reflect.InvocationTargetException; 12 import java.lang.reflect.Method; 13 import java.util.*; 14 15 16 import com.fuzhu.entity.Student; 17 import org.apache.poi.hssf.usermodel.HSSFCell; 18 import org.apache.poi.hssf.usermodel.HSSFCellStyle; 19 import org.apache.poi.hssf.usermodel.HSSFRow; 20 import org.apache.poi.hssf.usermodel.HSSFSheet; 21 import org.apache.poi.hssf.usermodel.HSSFWorkbook; 22 23 24 public class ExportBeanExcel<T> { 25 26 /** 27 * 这是一个通用的方法,利用了JAVA的反射机制,可以将放置在JAVA集合中并且符号一定条件的数据以EXCEL 的形式输出 28 * 29 * title 表格标题名 30 * headersName 表格属性列名数组 31 * headersId 表格属性列名对应的字段---你需要导出的字段名(为了更灵活控制你想要导出的字段) 32 * dtoList 需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象 33 * out 与输出设备关联的流对象,可以将EXCEL文档导出到本地文件或者网络中 34 */ 35 public void exportExcel(String title, List<String> headersName,List<String> headersId, 36 List<T> dtoList) { 37 /*(一)表头--标题栏*/ 38 Map<Integer, String> headersNameMap = new HashMap<>(); 39 int key=0; 40 for (int i = 0; i < headersName.size(); i++) { 41 if (!headersName.get(i).equals(null)) { 42 headersNameMap.put(key, headersName.get(i)); 43 key++; 44 } 45 } 46 /*(二)字段*/ 47 Map<Integer, String> titleFieldMap = new HashMap<>(); 48 int value = 0; 49 for (int i = 0; i < headersId.size(); i++) { 50 if (!headersId.get(i).equals(null)) { 51 titleFieldMap.put(value, headersId.get(i)); 52 value++; 53 } 54 } 55 /* (三)声明一个工作薄:包括构建工作簿、表格、样式*/ 56 HSSFWorkbook wb = new HSSFWorkbook(); 57 HSSFSheet sheet = wb.createSheet(title); 58 sheet.setDefaultColumnWidth((short)15); 59 // 生成一个样式 60 HSSFCellStyle style = wb.createCellStyle(); 61 HSSFRow row = sheet.createRow(0); 62 style.setAlignment(HSSFCellStyle.ALIGN_CENTER); 63 HSSFCell cell; 64 Collection c = headersNameMap.values();//拿到表格所有标题的value的集合 65 Iterator<String> it = c.iterator();//表格标题的迭代器 66 /*(四)导出数据:包括导出标题栏以及内容栏*/ 67 //根据选择的字段生成表头 68 short size = 0; 69 while (it.hasNext()) { 70 cell = row.createCell(size); 71 cell.setCellValue(it.next().toString()); 72 cell.setCellStyle(style); 73 size++; 74 } 75 //表格标题一行的字段的集合 76 Collection zdC = titleFieldMap.values(); 77 Iterator<T> labIt = dtoList.iterator();//总记录的迭代器 78 int zdRow =0;//列序号 79 while (labIt.hasNext()) {//记录的迭代器,遍历总记录 80 int zdCell = 0; 81 zdRow++; 82 row = sheet.createRow(zdRow); 83 T l = (T) labIt.next(); 84 // 利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值 85 Field[] fields = l.getClass().getDeclaredFields();//获得JavaBean全部属性 86 for (short i = 0; i < fields.length; i++) {//遍历属性,比对 87 Field field = fields[i]; 88 String fieldName = field.getName();//属性名 89 Iterator<String> zdIt = zdC.iterator();//一条字段的集合的迭代器 90 while (zdIt.hasNext()) {//遍历要导出的字段集合 91 if (zdIt.next().equals(fieldName)) {//比对JavaBean的属性名,一致就写入,不一致就丢弃 92 String getMethodName = "get" 93 + fieldName.substring(0, 1).toUpperCase() 94 + fieldName.substring(1);//拿到属性的get方法 95 Class tCls = l.getClass();//拿到JavaBean对象 96 try { 97 Method getMethod = tCls.getMethod(getMethodName, 98 new Class[] {});//通过JavaBean对象拿到该属性的get方法,从而进行操控 99 Object val = getMethod.invoke(l, new Object[] {});//操控该对象属性的get方法,从而拿到属性值 100 String textVal = null; 101 if (val!= null) { 102 textVal = String.valueOf(val);//转化成String 103 }else{ 104 textVal = null; 105 } 106 row.createCell((short) zdCell).setCellValue(textVal);//写进excel对象 107 zdCell++; 108 } catch (SecurityException e) { 109 e.printStackTrace(); 110 } catch (IllegalArgumentException e) { 111 e.printStackTrace(); 112 } catch (NoSuchMethodException e) { 113 e.printStackTrace(); 114 } catch (IllegalAccessException e) { 115 e.printStackTrace(); 116 } catch (InvocationTargetException e) { 117 e.printStackTrace(); 118 } 119 } 120 } 121 } 122 } 123 try { 124 FileOutputStream exportXls = new FileOutputStream("E://工单信息表.xls"); 125 wb.write(exportXls); 126 exportXls.close(); 127 System.out.println("导出成功!"); 128 } catch (FileNotFoundException e) { 129 System.out.println("导出失败!"); 130 e.printStackTrace(); 131 } catch (IOException e) { 132 System.out.println("导出失败!"); 133 e.printStackTrace(); 134 } 135 } 136 /* 137 使用例子 138 */ 139 public static void main(String [] args){ 140 List<String> listName = new ArrayList<>(); 141 listName.add("id"); 142 listName.add("名字"); 143 listName.add("性别"); 144 List<String> listId = new ArrayList<>(); 145 listId.add("id"); 146 listId.add("name"); 147 listId.add("sex"); 148 List<Student> list = new ArrayList<>(); 149 list.add(new Student(111,"张三asdf","男")); 150 list.add(new Student(111,"李四asd","男")); 151 list.add(new Student(111,"王五","女")); 152 153 154 ExportBeanExcel<Student> exportBeanExcelUtil = new ExportBeanExcel(); 155 exportBeanExcelUtil.exportExcel("测试POI导出EXCEL文档",listName,listId,list); 156 157 } 158 }
(四)工具注意点:
(1)应用泛型,代表任意一个符合javabean风格的类
(2)注意这里为了简单起见,boolean型的属性xxx的get器方式为getXxx(),而不是isXxx()
(3) T这里代表一个不确定是实体类,即参数实体
二、面向List-Map结构的导出工具:
(一)设计的关键:
(1)兼容普通List-Map结构;
(2)接口方法易用性;
(3)导出数据准确性;
(4)扩展性。
(二)基于POI抽象的关键步骤:
(1)设置表格标题
(2)设置标题栏
(3)设置内容栏(为了精确比对,需要给出标题栏对应的字段—dtoList(List-Map结构中的key))
(4)导出写入到流对象
(三)核心代码与demo:
1 package com.fuzhu.utils; 2 3 import org.apache.poi.hssf.usermodel.*; 4 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.util.*; 9 10 /** 11 * Created by 符柱成 on 2017/8/24. 12 */ 13 public class ExportMapExcel { 14 public void exportExcel(String title, List<String> headersName, List<String> headersId, 15 List<Map<String, Object>> dtoList) { 16 /* 17 (一)表头--标题栏 18 */ 19 Map<Integer, String> headersNameMap = new HashMap<>(); 20 int key = 0; 21 for (int i = 0; i < headersName.size(); i++) { 22 if (!headersName.get(i).equals(null)) { 23 headersNameMap.put(key, headersName.get(i)); 24 key++; 25 } 26 } 27 /* 28 (二)字段---标题的字段 29 */ 30 Map<Integer, String> titleFieldMap = new HashMap<>(); 31 int value = 0; 32 for (int i = 0; i < headersId.size(); i++) { 33 if (!headersId.get(i).equals(null)) { 34 titleFieldMap.put(value, headersId.get(i)); 35 value++; 36 } 37 } 38 /* 39 (三)声明一个工作薄:包括构建工作簿、表格、样式 40 */ 41 HSSFWorkbook wb = new HSSFWorkbook(); 42 HSSFSheet sheet = wb.createSheet(title); 43 sheet.setDefaultColumnWidth((short) 15); 44 // 生成一个样式 45 HSSFCellStyle style = wb.createCellStyle(); 46 HSSFRow row = sheet.createRow(0); 47 style.setAlignment(HSSFCellStyle.ALIGN_CENTER); 48 HSSFCell cell; 49 Collection c = headersNameMap.values();//拿到表格所有标题的value的集合 50 Iterator<String> headersNameIt = c.iterator();//表格标题的迭代器 51 /* 52 (四)导出数据:包括导出标题栏以及内容栏 53 */ 54 //根据选择的字段生成表头--标题 55 short size = 0; 56 while (headersNameIt.hasNext()) { 57 cell = row.createCell(size); 58 cell.setCellValue(headersNameIt.next().toString()); 59 cell.setCellStyle(style); 60 size++; 61 } 62 //表格一行的字段的集合,以便拿到迭代器 63 Collection zdC = titleFieldMap.values(); 64 Iterator<Map<String, Object>> titleFieldIt = dtoList.iterator();//总记录的迭代器 65 int zdRow = 1;//真正的数据记录的列序号 66 while (titleFieldIt.hasNext()) {//记录的迭代器,遍历总记录 67 Map<String, Object> mapTemp = titleFieldIt.next();//拿到一条记录 68 row = sheet.createRow(zdRow); 69 zdRow++; 70 int zdCell = 0; 71 Iterator<String> zdIt = zdC.iterator();//一条记录的字段的集合的迭代器 72 while (zdIt.hasNext()) { 73 String tempField =zdIt.next();//字段的暂存 74 if (mapTemp.get(tempField) != null) { 75 row.createCell((short) zdCell).setCellValue(String.valueOf(mapTemp.get(tempField)));//写进excel对象 76 zdCell++; 77 } 78 } 79 } 80 try { 81 FileOutputStream exportXls = new FileOutputStream("E://工单信息表Map.xls"); 82 wb.write(exportXls); 83 exportXls.close(); 84 System.out.println("导出成功!"); 85 } catch (FileNotFoundException e) { 86 System.out.println("导出失败!"); 87 e.printStackTrace(); 88 } catch (IOException e) { 89 System.out.println("导出失败!"); 90 e.printStackTrace(); 91 } 92 } 93 public static void main(String [] args) { 94 95 List<String> listName = new ArrayList<>(); 96 listName.add("id"); 97 listName.add("名字"); 98 listName.add("性别"); 99 List<String> listId = new ArrayList<>(); 100 listId.add("id"); 101 listId.add("name"); 102 listId.add("sex"); 103 104 List<Map<String,Object>> listB = new ArrayList<>(); 105 for (int t=0;t<6;t++){ 106 Map<String,Object> map = new HashMap<>(); 107 map.put("id",t); 108 map.put("name","abc"+t); 109 map.put("sex","男"+t); 110 listB.add(map); 111 } 112 System.out.println("listB : "+listB.toString()); 113 ExportMapExcel exportExcelUtil = new ExportMapExcel(); 114 exportExcelUtil.exportExcel("测试POI导出EXCEL文档",listName,listId,listB); 115 116 } 117 }