實現思路:html
1.因爲前端經過echarts生成圖形報表,因此後臺不必經過再弄一個插件生成一次圖表;前端
2.將echarts生成的圖片獲取base64編碼,將編碼內容post參數傳入後臺;後端
3.後臺接收到圖片參數進行解碼,生成本地圖片;瀏覽器
4.利用poi建立的HSSFPatriarch對象.createPicture()方法將圖片寫入excel單元格中。app
導出方法代碼:echarts
1 /** 2 *導出綜合得分統計 3 * @param fileName 4 * @param request 5 * @param response 6 * @param headInfo 7 * @param dataList 8 * @param evaluationId 9 * @throws DeException 10 */ 11 public void exportCompositeScore(String fileName, HttpServletRequest request, HttpServletResponse response, 12 String[] headInfo,List<Map<String,Object>> dataList,int evaluationId,String imgUrl,String message) throws DeException { 13 try { 14 Evaluation evaluation = evaluationDao.getEvaluationInfo(evaluationId); 15 int completeNum = evaluatorUserDao.getEvalStatusNum(evaluationId,Status.COMPLETED.name());//獲取答題結束的數量 16 int totalNum = evaluatorUserDao.getEvalTotalNum(evaluationId);//獲取測評人總數 17 HSSFWorkbook book = new HSSFWorkbook();// 建立Excel文件 18 HSSFSheet sheet = book.createSheet(fileName); // 建立一個工做薄 19 // 設置標題樣式 20 HSSFCellStyle tileStyle = book.createCellStyle(); 21 tileStyle.setAlignment(HSSFCellStyle.ALIGN_LEFT); // 水平佈局:居中 22 tileStyle.setVerticalAlignment(HSSFCellStyle.ALIGN_LEFT); 23 tileStyle.setWrapText(true); 24 HSSFFont nameRowFont = book.createFont(); 25 nameRowFont.setFontName("微軟雅黑"); 26 nameRowFont.setFontHeightInPoints((short) 8);// 設置字體大小 27 nameRowFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);// 粗體顯示 28 tileStyle.setFont(nameRowFont); 29 30 /*建立問卷標題行*/ 31 CellStyle wrapTextStyle = book.createCellStyle(); //建立自動換行樣式 32 wrapTextStyle.setWrapText(true); //設置換行 33 HSSFRow row0 = sheet.createRow(0); 34 row0.setHeight((short) 500);// 設置行高 35 HSSFCell nameCell = null; 36 for(int i = 0; i < headInfo.length; i++){ 37 nameCell = row0.createCell(i); 38 nameCell.setCellType(HSSFCell.CELL_TYPE_STRING); 39 if(i==0){ 40 nameCell.setCellStyle(wrapTextStyle); 41 nameCell.setCellValue(new HSSFRichTextString(evaluation.getEvaluation_subject()));//問卷標題 42 } 43 } 44 CellRangeAddress nameCellRange = new CellRangeAddress(0, 0, 0, headInfo.length-1);//標題合併單元格 45 sheet.addMergedRegion(nameCellRange); 46 47 /*建立問卷說明行*/ 48 HSSFRow row1 = sheet.createRow(1); 49 row1.setHeight((short) 500);// 設置行高 50 String desc = "測評人員:"+totalNum+"人"+" 已完成:"+completeNum+"人"; 51 for(int i = 0; i < headInfo.length; i++){ 52 HSSFCell cell = row1.createCell(i); 53 cell.setCellType(HSSFCell.CELL_TYPE_STRING); 54 if(i==0){ 55 cell.setCellValue(new HSSFRichTextString(desc)); 56 } 57 } 58 CellRangeAddress summaryCellRange = new CellRangeAddress(1, 1, 0, headInfo.length-1);//說明合併單元格 59 sheet.addMergedRegion(summaryCellRange); 60 //加權提示行 61 HSSFRow row2 = sheet.createRow(2); 62 HSSFCell messageCell = null; 63 for(int i = 0; i < headInfo.length; i++){ 64 messageCell = row2.createCell(i); 65 messageCell.setCellType(HSSFCell.CELL_TYPE_STRING); 66 if(i==0){ 67 messageCell.setCellStyle(wrapTextStyle); 68 messageCell.setCellValue(message);//問卷標題 69 } 70 } 71 sheet.addMergedRegion(new CellRangeAddress(2, 2, 0, headInfo.length-1));//合併單元格;起始行,結束行,起始列,結束列 72 if(StringUtils.isEmpty(message)){ 73 row2.setZeroHeight(true);//隱藏行 74 } 75 // EXCEL第四行表格標題 76 HSSFRow row3 = sheet.createRow(3); 77 HSSFCell cell = null; 78 row3.setHeight((short) 400);// 設置行高 79 for (int i = 0; i < headInfo.length; i++) { 80 /*設置列寬度*/ 81 if(i==1){ 82 sheet.setColumnWidth(i, 20 * 256); 83 }else if(i>1){ 84 sheet.setColumnWidth(i, 30 * 256); 85 }else{ 86 sheet.setColumnWidth(i, 12 * 256); 87 } 88 cell = row3.createCell(i); 89 cell.setCellValue(headInfo[i]); 90 cell.setCellStyle(tileStyle); 91 } 92 // EXCEL正文數據 93 Map<String,Object> answerObj = null; 94 HSSFRow dataRow = null; 95 Cell dataCell = null; 96 for (int j = 0; j < dataList.size(); j++) { 97 answerObj = dataList.get(j);//每一行的記錄 98 dataRow = sheet.createRow(j+4); 99 dataCell = dataRow.createCell(0);//工號 100 dataCell.setCellValue(answerObj.get("employee_id")+""); 101 dataCell = dataRow.createCell(1);//姓名 102 dataCell.setCellValue(answerObj.get("user_name")+""); 103 dataCell = dataRow.createCell(2);//部門 104 dataCell.setCellValue(answerObj.get("department")+""); 105 dataCell = dataRow.createCell(3);//我的平均分 106 dataCell.setCellValue(Tools.formatDouble(Double.parseDouble(answerObj.get("personal_score")+""))); 107 dataCell = dataRow.createCell(4);//測評平均分 108 dataCell.setCellValue(Tools.formatDouble(Double.parseDouble(answerObj.get("avg_score")+""))); 109 dataCell = dataRow.createCell(5);//分差值 110 dataCell.setCellValue(Tools.formatDouble(Double.parseDouble(answerObj.get("difference_val")+""))); 111 } 112 /*生成圖表*/ 113 if(StringUtils.isNotEmpty(imgUrl)) { 114 String[] imgUrlArr = imgUrl.split("base64,");//拆分base64編碼後部分 115 org.bouncycastle.util.encoders.Base64 decode = new org.bouncycastle.util.encoders.Base64(); 116 byte[] buffer = decode.decode(imgUrlArr[1]); 117 String picPath = request.getRealPath("")+ "/"+ UUID.randomUUID().toString() +".png"; 118 File file = new File(picPath);//圖片文件 119 //生成圖片 120 OutputStream out = new FileOutputStream(file);//圖片輸出流 121 out.write(buffer); 122 out.flush();//清空流 123 out.close();//關閉流 124 ByteArrayOutputStream outStream = new ByteArrayOutputStream(); // 將圖片寫入流中 125 BufferedImage bufferImg = ImageIO.read(new File(picPath)); 126 ImageIO.write(bufferImg, "PNG", outStream); // 利用HSSFPatriarch將圖片寫入EXCEL 127 HSSFPatriarch patri = sheet.createDrawingPatriarch(); 128 HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0,(short) 0, dataList.size() + 5, (short) 6, dataList.size() + 35); 129 patri.createPicture(anchor, book.addPicture(outStream.toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG)); 130 if(file.exists()){ 131 file.delete();//刪除圖片 132 } 133 } 134 135 //輸出excel文件名 136 fileName = Tools.processFileName(request, fileName);// 不一樣瀏覽器文件名亂碼解決 137 OutputStream os = response.getOutputStream();// 取得輸出流 138 response.reset();// 清空輸出流 139 response.setHeader("Connection", "close"); 140 response.setHeader("Content-Type", "application/octet-stream"); 141 response.setHeader("Content-Disposition", "attachment;filename="+fileName); 142 book.write(os); 143 os.flush(); 144 os.close(); 145 } catch (Exception e) { 146 logger.error("tid={} | 導出綜合得分表出現異常", ContextClient.getTid(), e); 147 throw new ServiceException(ServiceExceptionConstant.SYSTEM_EXCEPTION); 148 }finally{ 149 150 } 151 }
方法說明:dom
HSSFClientAnchor用於建立一個新的端錨,並設置錨的左下和右下座標,用於圖片插入,畫線等操做。佈局
HSSFClientAnchor(int dx1, int dy1, int dx2, int dy2, short col1, int row1, short col2, int row2)
dx1 dy1 起始單元格中的x,y座標.post
dx2 dy2 結束單元格中的x,y座標字體
col1,row1 指定起始的單元格,下標從0開始
col2,row2 指定結束的單元格 ,下標從0開始
來張圖更容易說明:
最後,看下生成的excel效果:
總結一下:
1.優勢:開發快捷,先後端圖片顯示樣式一致
2.缺點:不適合多圖片,base64編碼參數太長,請求參數太大,只能使用post方式。