平时我们在开发后端管理的系统时,经常会出现导出Excel的功能。这个功能很简单,但是呢,我一般就会使用公用的工具类,在一个Util中,暴露公用导出的接口,只需要传入需要导出的数据(一般使用list集合)以及需要导出的key-value字段和值的模板(这里使用了org.json,更加轻量话)。
一、废话不多说,直接先上暴露给用户的controller层的代码.这里呢,更改了header,通知浏览器打开下载功能(Content-Disposition 和attachment;filename一起使用)。然后只需要从数据库中调用需要导出的数据,这里我就直接调用所有的数据。
/** * 导出excel * @param response */ @RequestMapping(value = "exportExcel",method = RequestMethod.GET) public void exportExcel(HttpServletResponse response){ OutputStream out = null; try { out = response.getOutputStream(); response.reset(); String header = "attachment; filename=" + URLEncoder.encode("业主信息.xls", "UTF-8"); response.setHeader("Content-Disposition", header); response.setContentType("application/octet-stream; charset=utf-8"); List<Owner> owners = ownerService.findAll(); ownerService.exportExcel(owners,out); out.flush(); }catch (Exception e){ e.printStackTrace(); }finally { try{ if(out!=null){ out.close(); } }catch (Exception e){ e.printStackTrace(); } } }
二、Service的代码,对应 ownerService.exportExcel(owners,out); 传入了需要导出的集合,以及需要导出的out流。
1 @Override 2 public void exportExcel(List<Owner> owners, OutputStream out){ 3 JSONArray jsonArray = new JSONArray(); 4 List<Map<String, String>> eventRecordMapList = new ArrayList<Map<String, String>>(); 5 6 JSONObject jsonObject = new JSONObject(); 7 jsonObject.accumulate("headerName", "序号"); 8 jsonObject.accumulate("header", "id"); 9 jsonArray.put(jsonObject); 10 jsonObject = new JSONObject(); 11 jsonObject.accumulate("headerName", "业主姓名"); 12 jsonObject.accumulate("header", "name"); 13 jsonArray.put(jsonObject); 14 jsonObject = new JSONObject(); 15 jsonObject.accumulate("headerName", "业主开户银行"); 16 jsonObject.accumulate("header", "bankName"); 17 jsonArray.put(jsonObject); 18 jsonObject = new JSONObject(); 19 jsonObject.accumulate("headerName", "业主开户银行账号"); 20 jsonObject.accumulate("header", "bankAccount"); 21 jsonArray.put(jsonObject); 22 jsonObject = new JSONObject(); 23 jsonObject.accumulate("headerName", "供应商"); 24 jsonObject.accumulate("header", "vendor"); 25 jsonArray.put(jsonObject); 26 jsonObject = new JSONObject(); 27 jsonObject.accumulate("headerName", "代付金额"); 28 jsonObject.accumulate("header", "payed"); 29 jsonArray.put(jsonObject); 30 31 for (int i = 0; i < owners.size(); i++) { 32 33 34 Owner owner = owners.get(i); 35 Map<String, String> recordMap = new HashMap<String, String>(); 36 recordMap.put("id",owner.getId().toString()); 37 recordMap.put("name", owner.getName()); 38 recordMap.put("bankName", owner.getBankName()); 39 recordMap.put("bankAccount",owner.getBankAccount()); 40 recordMap.put("vendor",owner.getVendor()); 41 if (owner.getPayed()!=null){ 42 recordMap.put("payed",owner.getPayed().toString()); 43 }else { 44 recordMap.put("payed","0"); 45 } 46 47 48 eventRecordMapList.add(recordMap); 49 } 50 51 52 ExcelUtils exportExcel = new ExcelUtils(); 53 exportExcel.exportExcel("业主信息", jsonArray, eventRecordMapList, out); 54 }
这一块呢,使用了org.json ,如果亲们要使用我的代码,就要在项目中引入org.json ,maven引用如下
<dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>20151123</version> </dependency>
Service中的代码,主要是为了通过key-value的形式将数据全部进行整理,以便用通用的接口实现导出
三 、本块代码就是核心的Util中的通用工具类,这个通用工具类可以通过定制,继承的方式无限扩展适用的业务逻辑,比如可以扩展那些字段导出是需要下拉的,哪些是不能修改的等等,都可以扩展,这个考验扩展人的接口封装功底(我就特别喜欢封装公用接口给别人用,那种成就感很爽,不过就要考虑很多业务逻辑的情况),请打开查看哦,写得不是很复杂,不过也要慢慢看看就会懂了,就是一个公用方法。这样的好处就是,不管以后哪些板块用到导出功能,就不用再去写excel的操作代码了,只需要在模块的service中定义需要导出的字段,告诉Excel的栏目这些等等。还是那句话,util中的导出逻辑还可以继承修改,也更好的实现了扩展性。
1 public void exportExcel(String title, JSONArray jsonArray, List<Map<String, String>> eventRecordMapList, 2 OutputStream out) { 3 // 创建一个excel工作簿 4 HSSFWorkbook workbook = new HSSFWorkbook(); 5 HSSFSheet sheet = workbook.createSheet(title); 6 // excel列默认宽度 7 sheet.setDefaultColumnWidth(20); 8 9 // 第一行标题样式(白字蓝底) 10 HSSFCellStyle titleStyle = workbook.createCellStyle(); 11 HSSFPalette palette = workbook.getCustomPalette(); 12 palette.setColorAtIndex((short) 63, (byte) (50), (byte) (126), (byte) (179)); 13 titleStyle.setFillForegroundColor((short) 63); 14 titleStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); 15 titleStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); 16 titleStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); 17 titleStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); 18 titleStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); 19 titleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); 20 HSSFFont font = workbook.createFont(); 21 font.setColor(HSSFColor.WHITE.index); 22 font.setFontHeightInPoints((short) 12); 23 font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); 24 titleStyle.setFont(font); 25 titleStyle.setWrapText(false); 26 27 // 内容行样式 (白底黑字) 28 HSSFCellStyle contentStyle = workbook.createCellStyle(); 29 contentStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); 30 contentStyle.setFillForegroundColor(HSSFColor.WHITE.index); 31 contentStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); 32 contentStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN); 33 contentStyle.setBorderRight(HSSFCellStyle.BORDER_THIN); 34 contentStyle.setBorderTop(HSSFCellStyle.BORDER_THIN); 35 contentStyle.setAlignment(HSSFCellStyle.ALIGN_LEFT); 36 contentStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); 37 HSSFFont font2 = workbook.createFont(); 38 font2.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL); 39 contentStyle.setFont(font2); 40 contentStyle.setWrapText(true); 41 42 HSSFPatriarch patriarch = sheet.createDrawingPatriarch(); 43 HSSFComment comment = patriarch.createComment(new HSSFClientAnchor(0, 0, 0, 0, (short) 4, 2, (short) 6, 5)); 44 comment.setString(new HSSFRichTextString("数据列表")); 45 comment.setAuthor("csh"); 46 47 // 填充标题,就是第一行啦 48 HSSFRow row = sheet.createRow(0); 49 row.setHeight((short) 500); 50 for (short i = 0; i < jsonArray.length(); i++) { 51 HSSFCell cell = row.createCell(i); 52 cell.setCellStyle(titleStyle); 53 JSONObject jsonObject = jsonArray.getJSONObject(i); 54 HSSFRichTextString text = new HSSFRichTextString(jsonObject.getString("headerName")); 55 cell.setCellValue(text); 56 } 57 58 // 填充内容行,就是除第一行外的所有行,从第二行开始 59 for (int i = 0; i < eventRecordMapList.size(); i++) { 60 row = sheet.createRow(i + 1); 61 row.setHeight((short) 350); 62 Map<String, String> eventRecordMap = eventRecordMapList.get(i); 63 64 for (int j = 0; j < jsonArray.length(); j++) { 65 JSONObject jsonObject = jsonArray.getJSONObject(j); 66 HSSFCell cell = row.createCell(j); 67 cell.setCellStyle(contentStyle); 68 try { 69 String textValue = eventRecordMap.get(jsonObject.getString("header")); 70 71 if (textValue != null) { 72 Pattern p = Pattern.compile("^//d+(//.//d+)?$"); // 匹配是否是数值类型 73 Matcher matcher = p.matcher(textValue); 74 if (matcher.matches()) { 75 cell.setCellValue(Double.parseDouble(textValue)); 76 } else { 77 HSSFRichTextString richString = new HSSFRichTextString(textValue); 78 HSSFFont font3 = workbook.createFont(); 79 font3.setColor(HSSFColor.BLACK.index); 80 richString.applyFont(font3); 81 cell.setCellValue(richString); 82 } 83 } 84 85 } catch (Exception e) { 86 e.printStackTrace(); 87 } finally { 88 89 } 90 } 91 92 } 93 try { 94 workbook.write(out);// 将excel工作簿写入到输出流中 95 // workbook.close();//关闭 96 97 } catch (IOException e) { 98 e.printStackTrace(); 99 } 100 101 }