SpringBoot 導出 Excel

添加 maven 依賴

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.0</version>
        </dependency>

編寫工具類

  • 可以實現 
    • 1.導出Excel 到本地 / 瀏覽器
    • 2.導出包含多個 Sheet 的 Excel 到本地 / 瀏覽器
package com.geotmt.billingcenter.common.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Descriptinon: Excel 導出類
 * @Author:       yanghanwei
 * @Mail:         [email protected]
 * @CreateDate:   2018/12/3 17:15
 * @Version:      v1
 */
public class ExportExcelUtils {

    private static final String ATTR_ARR_STR = "attrArr";
    private static final String DATA_LIST_STR = "dataList";
    private static final String TITLE_ARR_STR = "titleArr";
    private static final String SHEET_NAME = "Sheet";
    private static final String SHEET_NAME_STR = "sheetName";
    /**
     * 默認單元格寬度
     */
    private static final Integer DEFAULT_CELL_WIDTH = 3000;

    private static FileOutputStream fout = null;
    private static OutputStream out = null;

    private static OutputStream setResponseHeaderFileName(HttpServletResponse response, String filename) throws IOException {
        response.setContentType("application/octet-stream;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(filename+".xls","UTF-8"));
        OutputStream out = new BufferedOutputStream(response.getOutputStream());
        return out;
    }

    private static final Logger logger = LoggerFactory.getLogger(ExportExcelUtils.class);

    /**
     * 導出 exccel到本地 工具類(多個sheet導出)
     * @param mapList
     * @param filePath 本地路徑
     * sheetName:   sheet名字
     * titleArr:    表頭中文名數組
     * attrArr:     數據對應的實體類屬性數組(與表頭一一對應)
     * dataList:    到處的數據list
     */
    public static void buildExcelTemplate( List<Map<String, Object>> mapList,String filePath, Integer cellWidth) {
        HSSFWorkbook wb = new HSSFWorkbook();
        FileOutputStream fout = null;
        try{
            // 將文件存到指定位置
            fout = new FileOutputStream(filePath);
            if (!mapList.isEmpty()) {
                for (int a = 0; a < mapList.size(); a++) {
                    String sheetName = "Sheet1";
                    if(!StringUtils.isEmpty(mapList.get(a).get(SHEET_NAME_STR))){
                        sheetName = String.valueOf(mapList.get(a).get(SHEET_NAME_STR));
                    }
                    String[] titleArr = (String[]) mapList.get(a).get("titleArr");
                    String[] attrArr = (String[]) mapList.get(a).get("attrArr");
                    Object dataList = mapList.get(a).get("dataList");
                    // 第二步,在webbook中添加一個sheet,對應Excel文件中的sheet
                    HSSFSheet sheetMonitor = wb.createSheet(sheetName);
                    // 第三步,在sheet中添加表頭第0行,注意老版本poi對Excel的行數列數有限制short
                    HSSFRow rowMonitor = sheetMonitor.createRow(0);
                    // 第四步,創建單元格,並設置值表頭 設置表頭居中
                    HSSFCellStyle style = ExportExcelUtils.getColumnTopStyle(wb);

                    HSSFCell cellMonitor = rowMonitor.createCell(0);
                    for (int i = 0; i < titleArr.length; i++) {
                        cellMonitor.setCellValue(titleArr[i]);
                        cellMonitor.setCellStyle(style);
                        cellMonitor = rowMonitor.createCell((i + 1));
                    }
                    String jsonString = JSONObject.toJSONString(dataList);
                    JSONArray jsonArray = JSONObject.parseArray(jsonString);
                    if (jsonArray != null && !jsonArray.isEmpty()) {
                        for (int i = 0; i < jsonArray.size(); i++) {
                            sheetMonitor.setColumnWidth(i, null == cellWidth ? DEFAULT_CELL_WIDTH : cellWidth);
                            Map<String, Object> map = JSONObject.parseObject(JSONObject.toJSONString(jsonArray.get(i)), Map.class);
                            if(null != map){
                                for (int j = 0; j < titleArr.length; j++) {
                                    rowMonitor = sheetMonitor.createRow(i + 1);
                                    // 第五步,寫入實體數據 實際應用中這些數據從數據庫得到,
                                    for (int k = 0; k < attrArr.length; k++) {
                                        if (map.containsKey(attrArr[k]) && !StringUtils.isEmpty(map.get(attrArr[k]))) {
                                            // 第四步,創建單元格,並設置值
                                            if(!StringUtils.isEmpty(map.get(attrArr[k]))){
                                                String value = String.valueOf(map.get(attrArr[k]));
                                                rowMonitor.createCell(k).setCellValue(value);
                                            }else{
                                                rowMonitor.createCell(k).setCellValue("");
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            wb.write(fout);
        }catch (Exception e){
            logger.error("導出Excel失敗,Exception:" + e);
            logger.info("導出Excel失敗,Exception:{0}", e);
        }finally {
            try {
                if(null != fout){
                    fout.close();
                }
            }catch (Exception e){
                logger.error("關閉流異常:[{}]",e);
            }
        }
    }

    /**
     * 導出 exccel 到瀏覽器工具類(1個sheet導出)
     * @param dataListForMap
     * sheetName:       sheet名字
     * titleArr:        表頭中文名數組
     * attrArr:         數據對應的實體類屬性數組(與表頭一一對應)
     * dataListForMap:  導出的數據list
     */
    public static void buildExcelTemplate(Map<String, Object> dataListForMap, HttpServletResponse response, String fileName, Integer cellWidth) {
        HSSFWorkbook wb = new HSSFWorkbook();
        // 第二步,在webbook中添加一個sheet,對應Excel文件中的sheet
        Object sheetName = dataListForMap.get("sheetName");
        HSSFSheet sheetMonitor = wb.createSheet(!StringUtils.isEmpty(sheetName) ? sheetName + "" : SHEET_NAME);
        // 第三步,在sheet中添加表頭第0行,注意老版本poi對Excel的行數列數有限制short
        HSSFRow rowMonitor = sheetMonitor.createRow(0);
        try{
            out = setResponseHeaderFileName(response,fileName);
            //創建excel標題,設置列寬
            createTitle(wb, rowMonitor, dataListForMap, sheetMonitor, cellWidth);
            //寫入數據
            writeData(sheetMonitor,1,dataListForMap);
            wb.write(out);
        }catch (Exception e){
            logger.info("導出Excel失敗,Exception:{}",e);
        }finally {
            try {
                out.close();
            }catch (Exception e){
                logger.error("關閉流異常:[{}]",e);
            }
        }
    }


    /**
     * 導出多個 sheet 到瀏覽器
     * @param mapList
     *      * sheetName:   sheet名字
     *      * titleArr:    表頭中文名數組
     *      * attrArr:     數據對應的實體類屬性數組(與表頭一一對應)
     *      * dataList:    到處的數據list
     * @param response
     * @param fileName      文件名稱
     */
    public static void buildExcelTemplate(List<Map<String, Object>> mapList, HttpServletResponse response, String fileName, Integer cellWidth) {
        HSSFWorkbook wb = new HSSFWorkbook();
        if(null != mapList && !mapList.isEmpty()){
            try{
                for (int i=0; i<mapList.size(); i++) {
                    Map<String, Object> dataListForMap = mapList.get(i);
                    // 第二步,在webbook中添加一個sheet,對應Excel文件中的sheet
                    Object sheetName = dataListForMap.get(SHEET_NAME_STR);
                    String sheetNameRt = !StringUtils.isEmpty(sheetName) ? sheetName + "" : SHEET_NAME + (i+1);
                    HSSFSheet sheetMonitor = wb.createSheet(sheetNameRt);
                    // 第三步,在sheet中添加表頭第0行,注意老版本poi對Excel的行數列數有限制short
                    HSSFRow rowMonitor = sheetMonitor.createRow(0);
                    out = setResponseHeaderFileName(response,fileName);
                    //創建excel標題
                    createTitle(wb, rowMonitor, dataListForMap, sheetMonitor, cellWidth);
                    //寫入數據
                    writeData(sheetMonitor,1,dataListForMap);
                }
                wb.write(out);
            }catch (IOException e){
                e.printStackTrace();
                logger.info("導出Excel失敗,Exception:{}",e);
            }catch (Exception e) {
                logger.info("導出Excel失敗,Exception:{}",e);
            }finally {
                try {
                    out.close();
                }catch (Exception e){
                    logger.error("關閉流異常:[{}]",e);
                }
            }
        }
    }

    /**
     * 創建excel標題
     * @param dataListForMap
     */
    private static void createTitle(HSSFWorkbook wb, HSSFRow rowMonitor, Map<String, Object> dataListForMap, HSSFSheet sheetMonitor, Integer cellWidth){
        String[] titleArr = (String[]) dataListForMap.get(TITLE_ARR_STR);

        //居中樣式
        HSSFCellStyle centerStyle = ExportExcelUtils.getColumnTopStyle(wb);

        for (int i = 0; i < titleArr.length; i++) {
            // 設置表格寬度(自適應)
            sheetMonitor.setColumnWidth(i, null == cellWidth ? DEFAULT_CELL_WIDTH : cellWidth);
            HSSFCell cellMonitor = rowMonitor.createCell(i);
            cellMonitor.setCellStyle(centerStyle);
            cellMonitor.setCellValue(titleArr[i]);
        }
    }

    /**
     * 寫入數據
     * @param sheetMonitor
     * @param startRow
     * @param dataListForMap
     */
    public static void writeData(HSSFSheet sheetMonitor, Integer startRow, Map<String, Object> dataListForMap){
        String[] titleArr = (String[]) dataListForMap.get(TITLE_ARR_STR);
        String[] attrArr = (String[]) dataListForMap.get(ATTR_ARR_STR);
        Object dataList = dataListForMap.get(DATA_LIST_STR);

        String jsonString = JSONObject.toJSONString(dataList);
        JSONArray jsonArray = JSONObject.parseArray(jsonString);
        if (jsonArray != null && !jsonArray.isEmpty()) {
            for (int i = 0; i < jsonArray.size(); i++) {
                Map<String, Object> map = JSONObject.parseObject(JSONObject.toJSONString(jsonArray.get(i)), Map.class);
                for (int j = 0; j < titleArr.length; j++) {
                    HSSFRow rowMonitor = sheetMonitor.createRow( i + startRow);
                    // 第五步,寫入實體數據 實際應用中這些數據從數據庫得到,
                    for (int k = 0; k < attrArr.length; k++) {
                        if (map != null && attrArr[k] != null && map.containsKey(attrArr[k]) && !StringUtils.isEmpty(map.get(attrArr[k]))) {
                            // 第四步,創建單元格,並設置值
                            if(!StringUtils.isEmpty(map.get(attrArr[k]))){
                                String value = String.valueOf(map.get(attrArr[k]));
                                rowMonitor.createCell(k).setCellValue(value);
                            }else{
                                rowMonitor.createCell(k).setCellValue("");
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 列頭單元格樣式
     * @param workbook
     * @return
     */
    private static HSSFCellStyle getColumnTopStyle(HSSFWorkbook workbook) {

        // 設置字體
        HSSFFont font = workbook.createFont();
        //設置字體大小
        font.setFontHeightInPoints((short)12);
        //字體加粗
        font.setBold(true);
        //設置字體名字
        font.setFontName("Courier New");
        //設置樣式;
        HSSFCellStyle style = workbook.createCellStyle();
        //設置底邊框;
        style.setBorderBottom(BorderStyle.THIN);
        //設置底邊框顏色;
        style.setBottomBorderColor(HSSFColor.HSSFColorPredefined.BLUE.getIndex());
        //設置左邊框;
        style.setBorderLeft(BorderStyle.THIN);
        //設置左邊框顏色;
        style.setLeftBorderColor(HSSFColor.HSSFColorPredefined.BLUE.getIndex());
        //設置右邊框;
        style.setBorderRight(BorderStyle.THIN);
        //設置右邊框顏色;
        style.setRightBorderColor(HSSFColor.HSSFColorPredefined.BLUE.getIndex());
        //設置頂邊框;
        style.setBorderTop(BorderStyle.THIN);
        //設置頂邊框顏色;
        style.setTopBorderColor(HSSFColor.HSSFColorPredefined.BLUE.getIndex());

        style.setFillBackgroundColor(HSSFColor.HSSFColorPredefined.DARK_RED.getIndex());
        style.setFillForegroundColor(HSSFColor.HSSFColorPredefined.DARK_RED.getIndex());
        //在樣式用應用設置的字體;
        style.setFont(font);
        //設置自動換行;
        style.setWrapText(false);
        //設置水平對齊的樣式爲居中對齊;
        style.setAlignment(HorizontalAlignment.CENTER);
        //設置垂直對齊的樣式爲居中對齊;
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        return style;

    }

    /**
     * 列數據信息單元格樣式
     * @param workbook
     * @return
     */
    private HSSFCellStyle getStyle(HSSFWorkbook workbook) {
        // 設置字體
        HSSFFont font = workbook.createFont();
        //設置字體大小
        font.setFontHeightInPoints((short)12);
        font.setFontName("Courier New");
        //設置樣式;
        HSSFCellStyle style = workbook.createCellStyle();
        //設置底邊框;
        style.setBorderBottom(BorderStyle.THIN);
        //設置底邊框顏色;
        style.setBottomBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
        //設置左邊框;
        style.setBorderLeft(BorderStyle.THIN);
        //設置左邊框顏色;
        style.setLeftBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
        //設置右邊框;
        style.setBorderRight(BorderStyle.THIN);
        //設置右邊框顏色;
        style.setRightBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
        //設置頂邊框;
        style.setBorderTop(BorderStyle.THIN);
        //設置頂邊框顏色;
        style.setTopBorderColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());
        //在樣式用應用設置的字體;
        style.setFillBackgroundColor(HSSFColor.HSSFColorPredefined.BRIGHT_GREEN.getIndex());
        style.setFont(font);
        //設置自動換行;
        style.setWrapText(false);
        //設置水平對齊的樣式爲居中對齊;
        style.setAlignment(HorizontalAlignment.CENTER);
        //設置垂直對齊的樣式爲居中對齊;
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        return style;

    }

    /**
     * 判斷是否是整數
     * @param str
     * @return
     */
    private static Pattern pattern = Pattern.compile("^\\d+$");
    public static boolean isIntNum(String str) {
        Matcher isIntNum = pattern.matcher(str);
        if (!isIntNum.matches()) {
            return false;
        }
        return true;
    }

    /**
     * 判斷是否是浮點數
     * @param str
     * @return
     */
    private static Pattern pattern2 = Pattern.compile("\\d+\\.\\d+$|-\\d+\\.\\d+$");
    public static boolean isDoubleNum(String str) {
        Matcher isDoubleNum = pattern2.matcher(str);
        if (!isDoubleNum.matches()) {
            return false;
        }
        return true;
    }
}

簡單使用

@ApiOperation(value = "導出成本統計")
    @RequestMapping(value = "/exportList",method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public void ExportConsumeStatis(@RequestBody ParamsCost obj,
                                    HttpServletResponse response){
        logger.info("導出成本統計,ParamsConsume:{}",obj);
        try{
            if(null == obj.getEffectStartTime() || null == obj.getEffectEndTime()){
                throw new MyException("開始時間和結束時間不能爲空!", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
            String startStr = GeoDateUtils.getDateStr(obj.getEffectStartTime(), GeoDateUtils.DATE_FORMAT2);
            String endStr = GeoDateUtils.getDateStr(obj.getEffectEndTime(), GeoDateUtils.DATE_FORMAT2);
            String fileName = startStr + "-" + endStr + "(成本統計)";
            List<CostStatisVo> consumeStatisVos = costStatisService.costStatisList(obj);
            if (null != consumeStatisVos) {
                consumeStatisVos.add(costStatisService.costStatisTotal(obj));
            }
            
            // 拼接 Excel 數據
            Map<String,Object> map = new HashMap<>(3);
            String[] titleArr = {"日期","產品","客戶","用戶","用戶賬號","用戶ID","運營商","內部接口","外部接口","計費數","金額"};
            String[] attrArr = {"dayFlag","productName","companyName","cuserName","account","cuserId","isp","interfaceName","outInterfaceName","countCharging","cost"};
            map.put("titleArr",titleArr);
            map.put("attrArr",attrArr);
            map.put("dataList", consumeStatisVos);
            ExportExcelUtils.buildExcelTemplate(map, response, fileName,4000);
        }catch (Exception e) {
            e.printStackTrace();
            logger.error("導出消耗統計,Exception:",e);
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章