java poi導出帶圖表的excel表格

實現思路: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方式。

 

HSSFClientAnchor 參數說明

相關文章
相關標籤/搜索