java 导出Excel 大数据量,自己经验总结!(二)
在上一次的基础上加上了样式,以及中文列名
1 package com.tommy.fundation.util; 2 3 import java.io.OutputStream; 4 import java.util.ArrayList; 5 import java.util.HashMap; 6 import java.util.Iterator; 7 import java.util.List; 8 import java.util.Map; 9 import java.util.Set; 10 11 import javax.servlet.http.HttpServletResponse; 12 13 import org.apache.poi.hssf.usermodel.HSSFWorkbook; 14 import org.apache.poi.hssf.usermodel.HSSFSheet; 15 import org.apache.poi.hssf.usermodel.HSSFCellStyle; 16 import org.apache.poi.hssf.usermodel.HSSFFont; 17 import org.apache.poi.hssf.usermodel.HSSFRow; 18 import org.apache.poi.hssf.usermodel.HSSFCell; 19 import org.apache.poi.ss.usermodel.CellStyle; 20 import org.apache.poi.ss.usermodel.Font; 21 import org.apache.poi.ss.usermodel.IndexedColors; 22 23 public class ExportExcel<T> { 24 public void doExcel(HttpServletResponse response, List<T> list, String fileName) throws Exception { 25 String[] columnNames = new String[0]; 26 doExcel(response, list , columnNames, fileName); 27 } 28 /** 29 * 导出多张excel表,解决xls格式行数65535的限制 30 * @author OnlyOne 31 * @param response 32 * @param list 需要处理的list数据集合 33 * @param columnNames 与实体属性一一对应的列名 34 * @param fileName 文件名 35 * @throws Exception 36 */ 37 public void doExcel(HttpServletResponse response, List<T> list, String[] columnNames, String fileName) throws Exception { 38 OutputStream os = response.getOutputStream();//获取输出流 39 response.reset(); 40 // 设置下载头部信息。Content-disposition为属性名。attachment表示以附件方式下载,如果要在页面中打开,则改为inline。filename为文件名 41 response.setContentType("application/vnd.ms-excel;charset=utf-8"); 42 response.setHeader("Content-disposition", "attachment;filename="+ new String((fileName + ".xls").getBytes(), "iso-8859-1")); 43 44 //将数据集合按65000个进行分割成多个子集合 45 Map<Integer, List<T>> sheetMap = doSheets(list); 46 // 创建excel工作簿 47 HSSFWorkbook wb = new HSSFWorkbook(); 48 //将map集合转换成set集合 49 Set<Integer> keys = sheetMap.keySet(); 50 51 // 创建两种单元格格式 52 HSSFCellStyle cs = wb.createCellStyle(); 53 HSSFCellStyle cs2 = wb.createCellStyle(); 54 55 // 创建两种字体 56 HSSFFont f = wb.createFont(); 57 HSSFFont f2 = wb.createFont(); 58 59 // 创建第一种字体样式(用于列名) 60 f.setFontHeightInPoints((short) 10); 61 f.setColor(IndexedColors.BLACK.getIndex()); 62 f.setBoldweight(Font.BOLDWEIGHT_BOLD); 63 64 // 创建第二种字体样式(用于值) 65 f2.setFontHeightInPoints((short) 10); 66 f2.setColor(IndexedColors.BLACK.getIndex()); 67 68 // 设置第一种单元格的样式(用于列名) 69 cs.setFont(f); 70 cs.setBorderLeft(CellStyle.BORDER_THIN); 71 cs.setBorderRight(CellStyle.BORDER_THIN); 72 cs.setBorderTop(CellStyle.BORDER_THIN); 73 cs.setBorderBottom(CellStyle.BORDER_THIN); 74 cs.setAlignment(CellStyle.ALIGN_CENTER); 75 76 // 设置第二种单元格的样式(用于值) 77 cs2.setFont(f2); 78 cs2.setBorderLeft(CellStyle.BORDER_THIN); 79 cs2.setBorderRight(CellStyle.BORDER_THIN); 80 cs2.setBorderTop(CellStyle.BORDER_THIN); 81 cs2.setBorderBottom(CellStyle.BORDER_THIN); 82 cs2.setAlignment(CellStyle.ALIGN_CENTER); 83 84 //对set集合进行遍历 85 for (Iterator<Integer> iterator = keys.iterator(); iterator.hasNext();) { 86 //获取遍历的下标 87 Integer sheetKey = iterator.next(); 88 // 创建一个sheet(页),并命名 89 HSSFSheet sheet = wb.createSheet("sheet"+sheetKey); 90 //获取一页的数据 91 List<T> sheetData = sheetMap.get(sheetKey); 92 //创建列名的行 93 HSSFRow firstRow = sheet.createRow(0); 94 //如果columnNames有值,则作为列名;如果没有,则实体的属性名作为列名 95 if(columnNames.length == 0){ 96 T en = (T) sheetData.get(0); 97 List<Object> titleList = RelectUtil.<T>reflectEntityAttribute(en); 98 for(int m=0; m<titleList.size(); m++){ 99 HSSFCell cell = firstRow.createCell(m); 100 cell.setCellValue(titleList.get(m+1).toString()); 101 cell.setCellStyle(cs); 102 } 103 }else{ 104 for(int m=0; m<columnNames.length; m++){ 105 HSSFCell cell = firstRow.createCell(m); 106 cell.setCellValue(columnNames[m]); 107 cell.setCellStyle(cs); 108 } 109 } 110 111 // 手动设置列宽。第一个参数表示要为第几列设;,第二个参数表示列的宽度,n为列高的像素数。 112 for(int i=0;i<columnNames.length;i++){ 113 sheet.setColumnWidth((short) i, (short) (35.7 * 100)); 114 } 115 116 //遍历一页的数据集合 117 for (int i = 0, len = sheetData.size(); i < len; i++) { 118 //获取数据实体 119 T en = (T) sheetData.get(i); 120 //反射获取行数据 121 List<Object> dataList = RelectUtil.<T>reflectEntity(en, en.getClass()); 122 //创建数据行,以第二行开始,第一行作为列名使用 123 HSSFRow row = sheet.createRow(i+1); 124 for(int m=0; m<dataList.size(); m++){ 125 HSSFCell cell = row.createCell(m); 126 cell.setCellValue(dataList.get(m).toString()); 127 cell.setCellStyle(cs2); 128 } 129 130 } 131 } 132 wb.write(os); 133 os.flush(); 134 os.close(); 135 } 136 /** 137 * 此方法将数据集合按65000个进行分割成多个子集合 138 * @author OnlyOne 139 * @param list 需要处理的list数据集合 140 * @return 141 */ 142 public Map<Integer, List<T>> doSheets(List<T> list){ 143 int count = list.size()/65000; 144 int yu = list.size() % 65000; 145 Map<Integer, List<T>> map = new HashMap<Integer, List<T>>(); 146 for (int i = 0; i <= count; i++) { 147 List<T> subList = new ArrayList<T>(); 148 if (i == count) { 149 subList = list.subList(i * 65000, 65000 * i + yu); 150 } else { 151 subList = list.subList(i * 65000, 65000 * (i + 1)); 152 } 153 map.put(i, subList); 154 } 155 return map; 156 } 157 }
辅助工具类
1 package com.tommy.fundation.util; 2 3 import java.lang.reflect.Field; 4 import java.lang.reflect.InvocationTargetException; 5 import java.lang.reflect.Method; 6 import java.util.ArrayList; 7 import java.util.Date; 8 import java.util.List; 9 10 public class RelectUtil { 11 public static <T> List<Object> reflectEntity(T model,Class<?> cals) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, NoSuchFieldException{ 12 List<Object> list = new ArrayList<Object>(); 13 Field[] field = model.getClass().getDeclaredFields(); //获取实体类的所有属性,返回Field数组 14 for(int j=0 ; j<field.length ; j++){ //遍历所有属性 15 String nam = field[j].getName(); //获取属性的名字 16 String name = nam; 17 name = name.substring(0,1).toUpperCase()+name.substring(1); 18 String type = field[j].getGenericType().toString(); //获取属性的类型 19 20 if(type.equals("class java.lang.String")){ //如果type是类类型,则前面包含"class ",后面跟类名 21 Method m = model.getClass().getMethod("get"+name); 22 String value = (String) m.invoke(model); //调用getter方法获取属性值 23 if(value != null){ 24 list.add(value); 25 }else{ 26 list.add(""); 27 } 28 } 29 30 if(type.equals("class java.lang.Integer") || type.equals("int")){ 31 Method m = model.getClass().getMethod("get"+name); 32 Integer value = (Integer) m.invoke(model); 33 if(value != null){ 34 list.add(value); 35 }else{ 36 list.add(""); 37 } 38 } 39 40 if(type.equals("class java.lang.Short") || type.equals("short")){ 41 Method m = model.getClass().getMethod("get"+name); 42 Short value = (Short) m.invoke(model); 43 if(value != null){ 44 list.add(value); 45 }else{ 46 list.add(""); 47 } 48 } 49 50 if(type.equals("class java.lang.Double") || type.equals("double")){ 51 Method m = model.getClass().getMethod("get"+name); 52 Double value = (Double) m.invoke(model); 53 if(value != null){ 54 list.add(value); 55 }else{ 56 list.add(""); 57 } 58 } 59 60 if(type.equals("class java.lang.Boolean") || type.equals("boolean")){ 61 Method m = model.getClass().getMethod("get"+name); 62 Boolean value = (Boolean) m.invoke(model); 63 if(value != null){ 64 list.add(value); 65 }else{ 66 list.add(""); 67 } 68 } 69 70 if(type.equals("class java.util.Date")){ 71 Method m = model.getClass().getMethod("get"+name); 72 Date value = (Date) m.invoke(model); 73 if(value != null){ 74 list.add(value); 75 }else{ 76 list.add(""); 77 } 78 } 79 } 80 return list; 81 } 82 public static <T> List<Object> reflectEntityAttribute(T model) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException, NoSuchFieldException { 83 List<Object> list = new ArrayList<Object>(); 84 Field[] field = model.getClass().getDeclaredFields(); //获取实体类的所有属性,返回Field数组 85 for (int j = 0; j < field.length; j++) { //遍历所有属性 86 String nam = field[j].getName(); //获取属性的名字 87 list.add(nam); 88 } 89 return list; 90 } 91 }
What a meaningless sense if losing myself,though owning all of the world.