Poi快速匯出百萬Excel,分多Excel匯出
阿新 • • 發佈:2020-12-16
Poi快速匯出百萬Excel,分多Excel匯出 直接用
package com.windwardbird.util.exportExcel; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; import java.io.Serializable; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; import static sun.net.www.protocol.http.HttpURLConnection.userAgent; /** * @PackageName: com.sf.util.exportExcel * @Author: bird * @Description: */ @Component public class ExportMultiExcelUtils implements Serializable { private static final long serialVersionUID = -3238218142023285526L; private static final Logger logger = LoggerFactory.getLogger(ExportMultiExcelUtils.class); private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH"); public static final String EXCEL_SUFFIX = ".xlsx"; public static final Integer CURRENT_MAX_EXCEL_DATA = 500000; public static String EXCEL_NAME = ""; public Integer EXCEL_NUMBER = 0; //預設生成excel個數 /** *@Description : 主邏輯入口 *@Param: [headerMap, tempDataList, tableName, response] *@return: void *@Author: bird */ public void ExportExcel(Map<String, Object> headerMap, List<Map<String, Object>> tempDataList, String tableName, HttpServletResponse response) throws Exception { logger.info("進入Excel工具類"); EXCEL_NAME=tableName; List<List<Object>> excelDataResult = new CopyOnWriteArrayList<>(new ArrayList<>()); //Excel對應行的資料 List<Object> headExcelKey = new CopyOnWriteArrayList<>(new ArrayList<>()); //獲取匯出表頭key容器 目的為了動態獲取對應資料 List<Object> headExcelValue = new CopyOnWriteArrayList<>(new ArrayList<>()); //獲取Excel表頭value容器匯出 目的作為表頭 getHeaderKeyAndValue(headerMap, headExcelValue, headExcelKey); //獲取excel的表頭key與value processingInputData(tempDataList, excelDataResult, headExcelKey);//處理資料 Integer excelTotal = excelDataResult.size(); if (excelTotal <= CURRENT_MAX_EXCEL_DATA) { generateOneExcel(tableName, response, excelDataResult, headExcelValue, excelTotal); //匯出單Excel } else { generateMultiExcel(tableName, response, excelDataResult, headExcelValue, excelTotal);//匯出多Excel } } private void generateOneExcel(String tableName, HttpServletResponse response, List<List<Object>> excelDataResult, List<Object> headExcelValue, Integer excelTotal) { List<List<Object>> excelTempDataResult = new CopyOnWriteArrayList<>(new ArrayList<>()); SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(); Sheet sheet = sxssfWorkbook.createSheet(tableName); excelTempDataResult.add(headExcelValue); for (int j = 0; j < excelTotal; j++) { excelTempDataResult.add(excelDataResult.get(j)); } insertDataToExcel(excelTempDataResult, excelTempDataResult.size(), sheet); logger.info("查詢資料小於"+CURRENT_MAX_EXCEL_DATA+"條"); exportRelationExcel(EXCEL_NAME, sxssfWorkbook,response); //匯出excel } private void generateMultiExcel(String tableName, HttpServletResponse response, List<List<Object>> excelDataResult, List<Object> headExcelValue, Integer excelTotal) { logger.info("查詢到的資料大於"+CURRENT_MAX_EXCEL_DATA+"條"); int flagNum = excelTotal % CURRENT_MAX_EXCEL_DATA; // 取模看是否需要多分Excel if (flagNum == 0) { EXCEL_NUMBER = excelTotal / CURRENT_MAX_EXCEL_DATA; } else { EXCEL_NUMBER = excelTotal / CURRENT_MAX_EXCEL_DATA + 1; } for (int i = 1; i <= EXCEL_NUMBER; i++) { //構造當前Excel資料 List<List<Object>> excelTempDataResult = new CopyOnWriteArrayList<>(new ArrayList<>()); ; SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(); Sheet sheet = sxssfWorkbook.createSheet(tableName); if (i == 1) { //ToDo: 取50萬整資料,單獨加表頭 excelTempDataResult.add(headExcelValue); for (int j = 0; j < CURRENT_MAX_EXCEL_DATA; j++) { excelTempDataResult.add(excelDataResult.get(j)); } } else { excelTempDataResult.add(headExcelValue); //新增每個Excel的表頭 for (int j = CURRENT_MAX_EXCEL_DATA * (i - 1); j < CURRENT_MAX_EXCEL_DATA * i; j++) { if (j > excelTotal) { break; } else if (j < excelTotal) { excelTempDataResult.add(excelDataResult.get(j)); } } } insertDataToExcel(excelTempDataResult, excelTempDataResult.size(), sheet); //匯出Excel exportRelationExcel(EXCEL_NAME, sxssfWorkbook,response); //匯出excel } } /** *@Description: 給Excel賦值 *@Param: [excelTempDataResult, size, sheet] *@return: void */ private void insertDataToExcel(List<List<Object>> excelTempDataResult, int size, Sheet sheet) { for (int i = 0; i < size; i++) { Row row = sheet.createRow(i); List<Object> cellValue = excelTempDataResult.get(i); for (int j = 0; j < cellValue.size(); j++) { row.createCell(j).setCellValue(String.valueOf(null==cellValue.get(j)?"":cellValue.get(j))); } } } /** *@Description : *@Param: [tempDataList, excelDataResult, headExcelKey] *@return: void */ private void processingInputData(List<Map<String, Object>> tempDataList, List<List<Object>> excelDataResult, List<Object> headExcelKey) { if(!tempDataList.isEmpty()&&tempDataList.size()>0){ tempDataList.forEach(tempData->{ List<Object> headExcelData = new ArrayList<>(); headExcelKey.forEach(key->{ headExcelData.add(tempData.get(key)); }); excelDataResult.add(headExcelData); }); } } /** *@Description : d *@Param: [EXCEL_NAME, sxssfWorkbook, response] *@return: void */ private void exportRelationExcel(String EXCEL_NAME, SXSSFWorkbook sxssfWorkbook,HttpServletResponse response) { response.setContentType("application/vnd.ms-excel"); String fileName = EXCEL_NAME+"-"+dateFormat.format((new Date()))+EXCEL_SUFFIX; String finalFileName ; try { if (StringUtils.contains(userAgent, "MSIE")) { finalFileName = URLEncoder.encode(fileName, "UTF8"); } else if (StringUtils.contains(userAgent, "Mozilla")) { finalFileName = new String(fileName.getBytes("GBK"), "ISO-8859-1"); } else { finalFileName = URLEncoder.encode(fileName, "UTF8"); } response.setHeader("Content-disposition", "attachment;filename=" + finalFileName); OutputStream outputStream = response.getOutputStream(); sxssfWorkbook.write(outputStream); outputStream.flush(); outputStream.close(); sxssfWorkbook.close(); } catch (IOException e) { logger.error("匯出失敗,失敗原因:{}");e.printStackTrace(); } } /** *@Description : 建立Excel並賦值給單元格 *@Param: [excelDataResult, EXCEL_NAME, tempDataList, headExcelKey] *@return: org.apache.poi.xssf.streaming.SXSSFWorkbook */ private SXSSFWorkbook getSheetsData(List<List<Object>> excelDataResult, String EXCEL_NAME, List<Map<String, Object>> tempDataList, List<Object> headExcelKey) { SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(); Sheet sheet = sxssfWorkbook.createSheet(EXCEL_NAME); if(!tempDataList.isEmpty()&&tempDataList.size()>0){ tempDataList.forEach(tempData->{ List<Object> headExcelData = new ArrayList<>(); headExcelKey.forEach(key->{ headExcelData.add(tempData.get(key)); }); excelDataResult.add(headExcelData); }); } for (int i = 0; i < excelDataResult.size(); i++) { Row row = sheet.createRow(i); List<Object> cellValue = excelDataResult.get(i); for (int j = 0; j < cellValue.size(); j++) { row.createCell(j).setCellValue(String.valueOf(null==cellValue.get(j)?"":cellValue.get(j))); } } return sxssfWorkbook; } /** *@Description :獲取匯出表頭的key值及value值 *@Param: [headerMap, headExcelValue, headExcelKey] *@return: void */ private void getHeaderKeyAndValue(Map<String,Object> headerMap,List<Object> headExcelValue, List<Object> headExcelKey) { for(Map.Entry<String,Object> entry: headerMap.entrySet()){ String key = entry.getKey(); Object value = entry.getValue(); headExcelValue.add(value); headExcelKey.add(key); } } }