JAVA 使用 Apache POI 導出 Excel 詳解


 POI全稱PoorObfuscation Implementation ,是Apache組件的一個開源項目,可以對微軟的Office一系列辦公軟件進行讀寫操作。

 實現方式有三種(建議SXSSF):

 1,HSSF是POI工程對Excel 97(-2007)文件操作的純Java實現 

  2,XSSF是POI工程對Excel 2007 OOXML (.xlsx)文件操作的純Java實現 

    3,從POI 3.8版本開始,提供了一種基於XSSF的低內存占用的API----SXSSF

    SXSSF通過一個滑動窗口來限制訪問Row的數量從而達到低內存占用的目錄,XSSF可以訪問所有行。舊的行數據不再出現在滑動窗口中並變得無法訪問,與此同時寫到磁盤上。 
在自動刷新的模式下,可以指定窗口中訪問Row的數量,從而在內存中保持一定數量的Row。當達到這一數量時,在窗口中產生新的Row數據,並將低索引的數據從窗口中移動到磁盤中。 
或者,滑動窗口的行數可以設定成自動增長的。它可以根據需要周期的根據一次明確的flushRow(int keepRows)調用來進行修改。

 

  1,使用的POM包

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.0.1</version>
        </dependency>            

 

  2,導出案例

/**
     * 票據匯總
     *
     * @param in:
     * @param response:
     * @return: com.jfa.common.utils.R
     * @author:
     */
    @PostMapping("/billSummary")
    public R billSummary(@RequestBody ExportExcelIn in, HttpServletResponse response) {
        exportExcelService.billSummary(in, response);
        return R.ok();
    }


/**
     * 票據匯總 excel報表
     *
     * @param in:
     * @param response:
     * @return: void
     * @author:
     */
    public void billSummary(ExportExcelIn in, HttpServletResponse response) {
        //如果參數為空,設置實際為當前年份
        if (in == null || StringUtils.isBlank(in.getYear())) {
            in.setYear(DUtils.fmtDateY(new Date()));
        }

        ExcelUtils excelUtils = new ExcelUtils();
        excelUtils.setResponse(response);
        //設置文件名稱
        excelUtils.setFileName(StringUtils.isNotBlank(in.getFileName()) ? in.getFileName() : "綜合分析".concat(Constant.HG).concat(String.valueOf(System.currentTimeMillis())));
        //文檔內超鏈接跳轉
        excelUtils.setLinkType(CommonsUtils.DOCUMENT);

        /** 根據時間段,查詢票據數據 */
        List<BillPollEntity> billPollList = billPollService.queryByBillByParams(in);
        Optional.ofNullable(billPollList).filter(s -> s.size() > 0).orElseThrow(() -> new RRException("當前時間數據為空,請重新選擇再導出"));

        if (billPollList != null && billPollList.size() > 0) {

            //根據出票日期、到期日、出票人、收款人 分組
            TreeMap<String, List<BillPollEntity>> billPollData = billPollList.stream().collect(Collectors.groupingBy(s -> DUtils.dateFmtYYMMDD(s.getDrawTime()).concat(Constant.HG).concat(DUtils.dateFmtYYMMDD(s.getDueTime())).concat(Constant.HG).concat(s.getDrawName().concat(s.getPayeeName())), TreeMap::new, Collectors.toList()));

            //組裝各Sheet數據
            List<List<Object[]>> retDataList = new ArrayList<>();

            //設置sheet名稱; 名稱規則:出票日+到期日+總票額(萬元)+總條數
            List<Object> sheetNameList = new ArrayList<>();
            sheetNameList.add("匯總");
            //存放sheet數據對象
            List<Object[]> sheetList = new ArrayList<>();

            /** ============== 匯總 數據組裝開始 ============== */
            //票據回款信息集合
            Map<String, BillBackInfoEntity> billBackDataMap = billBackInfoService.getAllBillBackList(ShiroUtils.getUserMark());

            /** 匯總 設置列頭 */
            sheetList.add(ExcelHeadUtil.getBillSummaryHead());
            /** 匯總 設置總計 */
            List<Object> sumValueList = new ArrayList<>();
            ExcelTools.setEmpty(sumValueList, 5);
            sumValueList.add(ExcelTools.setFormula(5, 3, (billPollData.size() + 2)));
            sumValueList.add(ExcelTools.setFormula(6, 3, (billPollData.size() + 2)));
            sumValueList.add(ExcelTools.setFormula(7, 3, (billPollData.size() + 2)));
            sheetList.add(ExcelTools.list2ObjArr(sumValueList));
            for (Map.Entry<String, List<BillPollEntity>> m : billPollData.entrySet()) {
                String key = m.getKey(); //
                List<BillPollEntity> dataList = m.getValue(); //

                String sheetName = key.substring(0, key.lastIndexOf(Constant.HG));
                //總票面額
                BigDecimal totalBillAmount = dataList.stream().map(BillPollEntity::getBillAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                sheetName = sheetName.concat(Constant.L_KH + Constant.fmtAMT(totalBillAmount) + "萬" + Constant.R_KH).concat(dataList.size() + "條");
                //添加sheet名稱
                sheetNameList.add(sheetName);
                //總貼現金額
                BigDecimal totalBackAmount = dataList.stream().map(t -> billBackDataMap.get(t.getBillNo()) != null ? billBackDataMap.get(t.getBillNo()).getBackAmount() : BigDecimal.ZERO).reduce(BigDecimal.ZERO, BigDecimal::add);
                //總利息
                BigDecimal totalInterest = dataList.stream().map(t -> billBackDataMap.get(t.getBillNo()) != null ? billBackDataMap.get(t.getBillNo()).getInterest() : BigDecimal.ZERO).reduce(BigDecimal.ZERO, BigDecimal::add);

                /** 匯總 設置內容 */
                List<Object> valueList = new ArrayList<>();
                valueList.add(sheetName);
                valueList.add(DUtils.dateFmtYMD(dataList.get(0).getDrawTime()));
                valueList.add(DUtils.dateFmtYMD(dataList.get(0).getDueTime()));
                valueList.add(dataList.get(0).getDrawName());
                valueList.add(dataList.get(0).getPayeeName());
                valueList.add(totalBillAmount);
                valueList.add(totalBackAmount);
                valueList.add(totalInterest);
                sheetList.add(ExcelTools.list2ObjArr(valueList));

            }
            retDataList.add(sheetList);
            /** ============== 匯總 數據組裝結束 ============== */

            //設置各Sheet名稱
            excelUtils.setSheetName(ExcelTools.list2StrArr(sheetNameList));
            if (Constant.WHETHERE_DETAIL.YES.equals(in.getWhethereDetail())) {
                /** 設置匯總分類的詳細數據 */
                setBillSummaryData(billPollData, retDataList, billBackDataMap);
            }
            //設置Sheet數據
            excelUtils.setDataLists(retDataList);
        }

        List<List<Object[]>> dataList = excelUtils.getDataLists();
        Optional.ofNullable(dataList).filter(s -> s.size() > 0).ifPresent(s -> {
            //固定列頭、表頭
            HashMap paneMap = new HashMap();
            ArrayList<Integer[]> paneList = new ArrayList<>();
            paneList.add(new Integer[]{3, 2});//凍結的列數、凍結的行數
            paneMap.put(1, paneList);

            //設置篩選
            HashMap filterMap = new HashMap();
            filterMap.put(1, setDataFilter(ExcelHeadUtil.getBillSummaryHead().length));

            for (int i = 1; i < s.size(); i++) {
                ArrayList<Integer[]> pList = new ArrayList<>();
                pList.add(new Integer[]{1, 2});
                paneMap.put(i + 1, pList);
                filterMap.put(i + 1, setDataFilter(ExcelHeadUtil.getBillSummaryChildHead().length));
            }
            excelUtils.setPaneMap(paneMap);
            excelUtils.setFilterMap(filterMap);

        });

        //設置數字精度
        excelUtils.setPrecision(2);

        //開始導出
        excelUtils.exportForExcelsOptimize();
    }


/**
     * 設置 票據匯總 excel報表數據
     *
     * @param billPollMap: 數據源
     * @param retDataList: Sheet數據
     * @return: java.util.List<java.util.List < java.lang.String [ ]>>
     * @author:
     */
    private List<List<Object[]>> setBillSummaryData(TreeMap<String, List<BillPollEntity>> billPollMap, List<List<Object[]>> retDataList, Map<String, BillBackInfoEntity> billBackDataMap) {

        for (Map.Entry<String, List<BillPollEntity>> m : billPollMap.entrySet()) {
            //
            List<BillPollEntity> dataList = m.getValue();
            //存放sheet數據對象
            List<Object[]> sheetList = new ArrayList<>();
            //設置列頭
            sheetList.add(ExcelHeadUtil.getBillSummaryChildHead());
            //票據種類
            Map<String, String> kindMap = billKindConfigService.getCtNMap();

            //設置頭部統計
            List<Object> totalList = new ArrayList<>();
            ExcelTools.setEmpty(totalList, 6);
            totalList.add(ExcelTools.setFormula(6, 3, (dataList.size() + 2)));
            ExcelTools.setEmpty(totalList, 3);
            totalList.add(ExcelTools.setFormula(10, 3, (dataList.size() + 2)));
            totalList.add(ExcelTools.setFormula(11, 3, (dataList.size() + 2)));
            ExcelTools.setEmpty(totalList, 1);
            sheetList.add(ExcelTools.list2ObjArr(totalList));

            dataList.forEach(d -> {
                //設置內容
                List<Object> valueList = new ArrayList<>();
                valueList.add(d.getBillNo());
                valueList.add(kindMap.get(d.getBillKind()));
                valueList.add(d.getDrawName());
                valueList.add(d.getPayeeName());
                valueList.add(DUtils.dateFmtYMD(d.getDrawTime()));
                valueList.add(DUtils.dateFmtYMD(d.getDueTime()));
                valueList.add(d.getBillAmount());
                valueList.add(BillStatusEnum.getName(d.getBillStatus()));
                BillBackInfoEntity billBackInfoEntity = billBackDataMap.get(d.getBillNo());
                if (billBackInfoEntity != null) {
                    valueList.add(DUtils.dateFmtYMD(billBackInfoEntity.getBackTime()));
                    valueList.add(String.valueOf(billBackInfoEntity.getInterestDays()));
                    valueList.add(billBackInfoEntity.getInterest());
                    valueList.add(billBackInfoEntity.getBackAmount());
                    valueList.add(String.valueOf(billBackInfoEntity.getInterestRate().multiply(new BigDecimal(100)).setScale(2)).concat("%"));
                } else {
                    ExcelTools.setEmpty(valueList, 5);
                }
                sheetList.add(ExcelTools.list2ObjArr(valueList));
            });
            retDataList.add(sheetList);
        }
        return retDataList;
    }
View Code

 


  3,導出工具類
 

  ExcelUtils:

package com.xxx.common.excel;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.jfa.common.excel.CommonsUtils.*;

/**
 * @ProjectName: git-dev
 * @Package: com.jfa.modules.peak.controller
 * @ClassName: ExcelUtils
 * @Author
 * @Description: Excel 導入導出操作相關工具類
 */
@Slf4j
public class ExcelUtils {


    private static Logger log = LoggerFactory.getLogger(ExcelUtils.class);
    private static final ThreadLocal<SimpleDateFormat> fmt = new ThreadLocal<>();
    private static final ThreadLocal<DecimalFormat> df = new ThreadLocal<>();
    private static final ThreadLocal<ExcelUtils> UTILS_THREAD_LOCAL = new ThreadLocal<>();
    private static final Integer DATE_LENGTH = 10;

    //    private static final String MESSAGE_FORMAT_df = "#.######";
    //    private static final String MESSAGE_FORMAT = "yyyy-MM-dd";


    private SimpleDateFormat getDateFormat() {
        SimpleDateFormat format = fmt.get();
        if (format == null) {
            //默認格式日期: "yyyy-MM-dd"
            format = new SimpleDateFormat(expectDateFormatStr, Locale.getDefault());
            fmt.set(format);
        }
        return format;
    }

    public DecimalFormat getDecimalFormat() {
        DecimalFormat format = df.get();
        if (format == null) {
            //默認數字格式: "#.######" 六位小數點
            format = new DecimalFormat(numeralFormat);
            df.set(format);
        }
        return format;
    }

    public static final ExcelUtils initialization() {
        ExcelUtils excelUtils = UTILS_THREAD_LOCAL.get();
        if (excelUtils == null) {
            excelUtils = new ExcelUtils();
            UTILS_THREAD_LOCAL.set(excelUtils);
        }
        return excelUtils;
    }

    public ExcelUtils() {
        filePath = this.getFilePath();
        dataLists = this.getDataLists();
        response = this.getResponse();
        regionMap = this.getRegionMap();
        mapColumnWidth = this.getMapColumnWidth();
        styles = this.getStyles();
        paneMap = this.getPaneMap();
        fileName = this.getFileName();
        sheetName = this.getSheetName();
        labelName = this.getLabelName();
        rowStyles = this.getRowStyles();
        columnStyles = this.getColumnStyles();
        dropDownMap = this.getDropDownMap();
        numeralFormat = this.getNumeralFormat();
        dateFormatStr = this.getDateFormatStr();
        expectDateFormatStr = this.getExpectDateFormatStr();
        defaultColumnWidth = this.getDefaultColumnWidth();
        fontSize = this.getFontSize();
        precision = this.getPrecision();
        linkType = this.getLinkType();
        filterMap = this.getFilterMap();

    }


    /**
     * web 響應(response)
     * Excel導出:有樣式(行、列、單元格樣式)、自適應列寬
     * 功能描述: excel 數據導出、導出模板
     * 更新日志:
     * 1.response.reset();注釋掉reset,否在會出現跨域錯誤。[2018-05-18]
     * 2.新增導出多個單元。[2018-08-08]
     * 3.poi官方建議大數據量解決方案:SXSSFWorkbook。[2018-08-08]
     * 4.自定義下拉列表:對每個單元格自定義下拉列表。[2018-08-08]
     * 5.數據遍歷方式換成數組(效率較高)。[2018-08-08]
     * 6.可提供模板下載。[2018-08-08]
     * 7.每個表格的大標題[2018-09-14]
     * 8.自定義列寬:對每個單元格自定義列寬[2018-09-18]
     * 9.自定義樣式:對每個單元格自定義樣式[2018-10-22]
     * 10.自定義單元格合並:對每個單元格合並[2018-10-22]
     * 11.固定表頭[2018-10-23]
     * 12.自定義樣式:單元格自定義某一列或者某一行樣式[2018-11-12]
     * 13.忽略邊框(默認是有邊框)[2018-11-15]
     * 14.函數式編程換成面向對象編程[2018-12-06-5]
     * 15.單表百萬數據量導出時樣式設置過多,導致速度慢(行、列、單元格樣式暫時控制10萬行、超過無樣式)[2019-01-30]
     * 版  本:
     * 1.apache poi 3.17
     * 2.apache poi-ooxml  3.17
     *
     * @return
     */
    public Boolean exportForExcelsOptimize() {
        long startTime = System.currentTimeMillis();
        log.info("=== ===  === :Excel tool class export start run!");
        SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(1000);
        OutputStream outputStream = null;
        SXSSFRow sxssfRow = null;
        try {
            // 設置數據
            setDataList(sxssfWorkbook, sxssfRow, dataLists, regionMap, mapColumnWidth, styles, paneMap, sheetName, labelName, rowStyles, columnStyles, dropDownMap, defaultColumnWidth, fontSize,linkType,slashMap,precision,filterMap,rowStyleMap,rowList);
            // io 響應
            setIo(sxssfWorkbook, outputStream, fileName, sheetName, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("=== ===  === :Excel tool class export run time:" + (System.currentTimeMillis() - startTime) + " ms!");
        return true;
    }


    /**
     * Excel導出:無樣式(行、列、單元格樣式)、自適應列寬
     * web 響應(response)
     *
     * @return
     */
    public Boolean exportForExcelsNoStyle() {
        long startTime = System.currentTimeMillis();
        log.info("=== ===  === :Excel tool class export start run!");
        SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(1000);
        OutputStream outputStream = null;
        SXSSFRow sxssfRow = null;
        try {
            setDataListNoStyle(sxssfWorkbook, sxssfRow, dataLists, regionMap, mapColumnWidth, paneMap, sheetName, labelName, dropDownMap, defaultColumnWidth, fontSize,linkType,precision);
            setIo(sxssfWorkbook, outputStream, fileName, sheetName, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("=== ===  === :Excel tool class export run time:" + (System.currentTimeMillis() - startTime) + " ms!");
        return true;
    }


    /**
     * 功能描述:
     * 1.excel 模板數據導入。
     * <p>
     * 更新日志:
     * 1.共用獲取Excel表格數據。
     * 2.多單元數據獲取。
     * 3.多單元從第幾行開始獲取數據[2018-09-20]
     * 4.多單元根據那些列為空來忽略行數據[2018-10-22]
     * <p>
     * 版  本:
     * 1.apache poi 3.17
     * 2.apache poi-ooxml  3.17
     *
     * @param book           Workbook對象(不可為空)
     * @param sheetName      多單元數據獲取(不可為空)
     * @param indexMap       多單元從第幾行開始獲取數據,默認從第二行開始獲取(可為空,如 hashMapIndex.put(1,3); 第一個表格從第三行開始獲取)
     * @param continueRowMap 多單元根據那些列為空來忽略行數據(可為空,如 mapContinueRow.put(1,new Integer[]{1, 3}); 第一個表格從1、3列為空就忽略)
     * @return
     */
    @SuppressWarnings({"deprecation", "rawtypes"})
    public static List<List<LinkedHashMap<String, String>>> importForExcelData(Workbook book, String[] sheetName, HashMap indexMap, HashMap continueRowMap) {
        long startTime = System.currentTimeMillis();
        log.info("=== ===  === :Excel tool class export start run!");
        try {
            List<List<LinkedHashMap<String, String>>> returnDataList = new ArrayList<>();
            for (int k = 0; k <= sheetName.length - 1; k++) {
                //  得到第K個工作表對象、得到第K個工作表中的總行數。
                Sheet sheet = book.getSheetAt(k);
                int rowCount = sheet.getLastRowNum() + 1;
                Row valueRow = null;

                List<LinkedHashMap<String, String>> rowListValue = new ArrayList<>();
                LinkedHashMap<String, String> cellHashMap = null;

                int irow = 1;
                //  第n個工作表:從開始獲取數據、默認第一行開始獲取。
                if (indexMap != null && indexMap.get(k + 1) != null) {
                    irow = Integer.valueOf(indexMap.get(k + 1).toString()) - 1;
                }
                //  第n個工作表:數據獲取。
                for (int i = irow; i < rowCount; i++) {
                    valueRow = sheet.getRow(i);
                    if (valueRow == null) {
                        continue;
                    }

                    //  第n個工作表:從開始列忽略數據、為空就跳過。
                    if (continueRowMap != null && continueRowMap.get(k + 1) != null) {
                        int continueRowCount = 0;
                        Integer[] continueRow = (Integer[]) continueRowMap.get(k + 1);
                        for (int w = 0; w <= continueRow.length - 1; w++) {
                            Cell valueRowCell = valueRow.getCell(continueRow[w] - 1);
                            if (valueRowCell == null || isBlank(valueRowCell.toString())) {
                                continueRowCount = continueRowCount + 1;
                            }
                        }
                        if (continueRowCount == continueRow.length) {
                            continue;
                        }
                    }

                    cellHashMap = new LinkedHashMap<>();

                    //  第n個工作表:獲取列數據。
                    for (int j = 0; j < valueRow.getLastCellNum(); j++) {
                        cellHashMap.put(Integer.toString(j), getCellVal(valueRow.getCell(j)));
                    }
                    if (cellHashMap.size() > 0) {
                        rowListValue.add(cellHashMap);
                    }
                }
                returnDataList.add(rowListValue);
            }
            log.info("=== ===  === :Excel tool class export run time:" + (System.currentTimeMillis() - startTime) + " ms!");
            return returnDataList;
        } catch (Exception e) {
            log.debug("=== ===  === :Andyczy ExcelUtils Exception Message:Excel tool class export exception !");
            e.printStackTrace();
            return null;
        }
    }


    /**
     * response 響應
     *
     * @param sxssfWorkbook
     * @param outputStream
     * @param fileName
     * @param sheetName
     * @param response
     * @throws Exception
     */
    private static void setIo(SXSSFWorkbook sxssfWorkbook, OutputStream outputStream, String fileName, String[] sheetName, HttpServletResponse response) throws Exception {
        try {
            if (response != null) {
                response.setCharacterEncoding("utf-8");
                response.setHeader("Charset", "UTF-8");
                response.setHeader("Content-Type", "application/force-download");
                response.setHeader("Content-Type", "application/vnd.ms-excel");
                response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(fileName == null ? sheetName[0] : fileName, "utf8") + ".xlsx");
                response.flushBuffer();
                outputStream = response.getOutputStream();
            }
            writeAndColse(sxssfWorkbook, outputStream);
        } catch (Exception e) {
            e.getSuppressed();
        }
    }


    /**
     * 功能描述: 獲取Excel單元格中的值並且轉換java類型格式
     *
     * @param cell
     * @return
     */
    private static String getCellVal(Cell cell) {
        String val = null;
        if (cell != null) {
            CellType cellType = cell.getCellType();
            switch (cellType) {
                case NUMERIC:
                    if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
                        val = ExcelUtils.initialization().getDateFormat().format(cell.getDateCellValue());
                    } else {
                        val = ExcelUtils.initialization().getDecimalFormat().format(cell.getNumericCellValue());
                    }
                    break;
                case STRING:
                    if (cell.getStringCellValue().trim().length() >= DATE_LENGTH && verificationDate(cell.getStringCellValue(), ExcelUtils.initialization().dateFormatStr)) {
                        val = strToDateFormat(cell.getStringCellValue(), ExcelUtils.initialization().dateFormatStr, ExcelUtils.initialization().expectDateFormatStr);
                    } else {
                        val = cell.getStringCellValue();
                    }
                    break;
                case BOOLEAN:
                    val = String.valueOf(cell.getBooleanCellValue());
                    break;
                case BLANK:
                    val = cell.getStringCellValue();
                    break;
                case ERROR:
                    val = "錯誤";
                    break;
                case FORMULA:
                    try {
                        val = String.valueOf(cell.getStringCellValue());
                    } catch (IllegalStateException e) {
                        val = String.valueOf(cell.getNumericCellValue());
                    }
                    break;
                default:
                    val = cell.getRichStringCellValue() == null ? null : cell.getRichStringCellValue().toString();
            }
        } else {
            val = "";
        }
        return val;
    }

    /**
     * 導出數據必填
     */
    private List<List<Object[]>> dataLists;
    /**
     * sheet名稱必填
     */
    private String[] sheetName;
    /**
     * 每個表格的大標題
     */
    private String[] labelName;
    /**
     * 頁面響應
     */
    private HttpServletResponse response;

    /**
     * 自定義:單元格合並
     */
    private HashMap regionMap;
    /**
     * 自定義:對每個單元格自定義列寬
     */
    private HashMap mapColumnWidth;
    /**
     * 自定義:每一個單元格樣式
     */
    private HashMap styles;
    /**
     * 自定義:固定表頭
     */
    private HashMap paneMap;
    /**
     * 自定義:設置斜線
     */
    private HashMap slashMap;
    /**
     * 自定義:某一行樣式
     */
    private HashMap rowStyles;
    /**
     * 自定義:某一列樣式
     */
    private HashMap columnStyles;
    /**
     * 自定義:對每個單元格自定義下拉列表
     */
    private HashMap dropDownMap;
    /**
     * 文件名稱
     */
    private String fileName;
    /**
     * 導出本地路徑
     */
    private String filePath;

    /**
     * 導出數字格式化:默認是保留六位小數點
     */
    private String numeralFormat;

    /**
     * 導出日期格式化:默認是"yyyy-MM-dd"格式
     */
    private String dateFormatStr;
    /**
     * 期望轉換后的日期格式:默認是 dateFormatStr
     */
    private String expectDateFormatStr;

    /**
     * 默認列寬大小:默認16
     */
    private Integer defaultColumnWidth;
    /**
     * 默認字體大小:默認12號字體
     */
    private Integer fontSize;

    /**
     * 超鏈接類型;DOCUMENT = 文檔
     */
    private String linkType;

    /**
     * 自定義數字精度
     */
    private Integer precision = 0;

    /**
     * 自定義過濾列
     */
    private HashMap filterMap;

    /**
     * 自定義行 樣式
     */
    private HashMap rowStyleMap;

    /**
     * 自定義行 樣式
     */
    private List<Integer> rowList;

    public Integer getFontSize() {
        if (fontSize == null) {
            fontSize = 12;
        }
        return fontSize;
    }

    public void setFontSize(Integer fontSize) {
        this.fontSize = fontSize;
    }

    public Integer getDefaultColumnWidth() {
        if (defaultColumnWidth == null) {
            defaultColumnWidth = 30;
        }
        return defaultColumnWidth;
    }

    public void setDefaultColumnWidth(Integer defaultColumnWidth) {
        this.defaultColumnWidth = defaultColumnWidth;
    }

    public void setDateFormatStr(String dateFormatStr) {
        if (dateFormatStr == null) {
            dateFormatStr = "yyyy-MM-dd";
        }
        this.dateFormatStr = dateFormatStr;
    }

    public String getDateFormatStr() {
        if (dateFormatStr == null) {
            dateFormatStr = "yyyy-MM-dd";
        }
        return dateFormatStr;
    }

    public String getExpectDateFormatStr() {
        if (expectDateFormatStr == null) {
            expectDateFormatStr = dateFormatStr;
        }
        return expectDateFormatStr;
    }

    public void setExpectDateFormatStr(String expectDateFormatStr) {
        if (expectDateFormatStr == null) {
            expectDateFormatStr = dateFormatStr;
        }
        this.expectDateFormatStr = expectDateFormatStr;
    }

    public void setNumeralFormat(String numeralFormat) {
        if (numeralFormat == null) {
            numeralFormat = "#.######";
        }
        this.numeralFormat = numeralFormat;
    }

    public String getNumeralFormat() {
        if (numeralFormat == null) {
            numeralFormat = "#.######";
        }
        return numeralFormat;
    }


    public List<List<Object[]>> getDataLists() {
        return dataLists;
    }

    public void setDataLists(List<List<Object[]>> dataLists) {
        this.dataLists = dataLists;
    }

    public String[] getSheetName() {
        return sheetName;
    }

    public void setSheetName(String[] sheetName) {
        this.sheetName = sheetName;
    }

    public String[] getLabelName() {
        return labelName;
    }

    public void setLabelName(String[] labelName) {
        this.labelName = labelName;
    }

    public HttpServletResponse getResponse() {
        return response;
    }

    public void setResponse(HttpServletResponse response) {
        this.response = response;
    }


    public HashMap getRegionMap() {
        return regionMap;
    }

    public void setRegionMap(HashMap regionMap) {
        this.regionMap = regionMap;
    }

    public HashMap getMapColumnWidth() {
        return mapColumnWidth;
    }

    public void setMapColumnWidth(HashMap mapColumnWidth) {
        this.mapColumnWidth = mapColumnWidth;
    }

    public HashMap getStyles() {
        return styles;
    }

    public void setStyles(HashMap styles) {
        this.styles = styles;
    }

    public HashMap getPaneMap() {
        return paneMap;
    }

    public void setPaneMap(HashMap paneMap) {
        this.paneMap = paneMap;
    }

    public HashMap getRowStyles() {
        return rowStyles;
    }

    public void setRowStyles(HashMap rowStyles) {
        this.rowStyles = rowStyles;
    }

    public HashMap getColumnStyles() {
        return columnStyles;
    }

    public void setColumnStyles(HashMap columnStyles) {
        this.columnStyles = columnStyles;
    }

    public HashMap getDropDownMap() {
        return dropDownMap;
    }

    public void setDropDownMap(HashMap dropDownMap) {
        this.dropDownMap = dropDownMap;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public String getLinkType() {
        return linkType;
    }

    public void setLinkType(String linkType) {
        this.linkType = linkType;
    }

    public HashMap getSlashMap() {
        return slashMap;
    }

    public void setSlashMap(HashMap slashMap) {
        this.slashMap = slashMap;
    }

    public Integer getPrecision() {
        return precision;
    }

    public void setPrecision(Integer precision) {
        this.precision = precision;
    }

    public HashMap getFilterMap() {
        return filterMap;
    }

    public void setFilterMap(HashMap filterMap) {
        this.filterMap = filterMap;
    }

    public HashMap getRowStyleMap() {
        return rowStyleMap;
    }

    public void setRowStyleMap(HashMap rowStyleMap) {
        this.rowStyleMap = rowStyleMap;
    }

    public List<Integer> getRowList() {
        return rowList;
    }

    public void setRowList(List<Integer> rowList) {
        this.rowList = rowList;
    }
}
View Code

  

  CommonsUtils:

package com.xxx.common.excel;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.streaming.SXSSFDrawing;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.text.AttributeSet;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.apache.poi.ss.usermodel.ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE;
import static org.apache.poi.ss.util.CellUtil.createCell;

/**
 * @ProjectName: git-dev
 * @Package: com.jfa.common.excel
 * @ClassName: CommonsUtils
 * @Author:
 * @Description:
 */
public class CommonsUtils {

    private static Logger log = LoggerFactory.getLogger(CommonsUtils.class);

    private static final String DataValidationError1 = "Excel表格提醒:";
    private static final String DataValidationError2 = "數據不規范,請選擇表格下拉列表中的數據!";
    public static final Integer MAX_ROWSUM = 1048570;
    public static final Integer MAX_ROWSYTLE = 100000;
    public static final String BIGDECIMAL_CLASS = "class java.math.BigDecimal";
    /**
     * 超鏈接類型;DOCUMENT = 文檔
     */
    public static final String DOCUMENT = "DOCUMENT";
    /**
     * 超鏈接類型;DOCUMENT = 文檔
     */
    public static final String GS = "公式:";


    /**
     * 設置數據:有樣式(行、列、單元格樣式)
     *
     * @param wb
     * @param sxssfRow
     * @param dataLists
     * @param regionMap
     * @param columnMap
     * @param styles
     * @param paneMap
     * @param sheetName
     * @param labelName
     * @param rowStyles
     * @param columnStyles
     * @param dropDownMap
     * @throws Exception
     */
    public static void setDataList(SXSSFWorkbook wb, SXSSFRow sxssfRow, List<List<Object[]>> dataLists,
                                   HashMap regionMap, HashMap columnMap, HashMap styles, HashMap paneMap,
                                   String[] sheetName, String[] labelName, HashMap rowStyles, HashMap columnStyles,
                                   HashMap dropDownMap, Integer defaultColumnWidth, Integer fontSize, String linkType, HashMap slashMap, Integer precision, HashMap filterMap, HashMap rowStyleMap, List<Integer> rowList) throws Exception {
        if (dataLists == null) {
            log.debug("=== ===  === :Andyczy ExcelUtils Exception Message:Export data(type:List<List<String[]>>) cannot be empty!");
        }
        if (sheetName == null) {
            log.debug("=== ===  === :Andyczy ExcelUtils Exception Message:Export sheet(type:String[]) name cannot be empty!");
        }
        int k = 0;
        for (List<Object[]> listRow : dataLists) {
            SXSSFSheet sxssfSheet = wb.createSheet();
            sxssfSheet.setForceFormulaRecalculation(true);
//            sxssfSheet.setDefaultColumnWidth(defaultColumnWidth);
            wb.setSheetName(k, sheetName[k]);
            CellStyle cellStyle = wb.createCellStyle();
            XSSFFont font = (XSSFFont) wb.createFont();
            SXSSFDrawing sxssfDrawing = sxssfSheet.createDrawingPatriarch();
            int jRow = 0;

            //  自定義:大標題(看該方法說明)。
            jRow = setLabelName(jRow, k, wb, labelName, sxssfRow, sxssfSheet, listRow);

            //  自定義:每個表格固定表頭(看該方法說明)。
            if (paneMap != null && paneMap.get(k + 1) != null) {
                createFreezePane(sxssfSheet, (ArrayList<Integer[]>) paneMap.get(k + 1));
            }
            //  自定義:設置斜線
            if (slashMap != null && slashMap.get(k + 1) != null) {
                createSlash(wb, sxssfSheet, (ArrayList<Integer[]>) slashMap.get(k + 1));
            }
            //  自定義:過濾數據
            if (filterMap != null && filterMap.get(k + 1) != null) {
                createFilter(sxssfSheet, filterMap, k + 1);
            }
            //  自定義:每個單元格自定義合並單元格:對每個單元格自定義合並單元格(看該方法說明)。
            if (regionMap != null) {
                setMergedRegion(sxssfSheet, (ArrayList<Integer[]>) regionMap.get(k + 1));
            }
            //  自定義:每個單元格自定義下拉列表:對每個單元格自定義下拉列表(看該方法說明)。
            if (dropDownMap != null) {
                setDataValidation(sxssfSheet, (List<String[]>) dropDownMap.get(k + 1), listRow.size());
            }
            //  自定義:每個表格自定義列寬:對每個單元格自定義列寬(看該方法說明)。
            if (columnMap != null) {
                setColumnWidth(sxssfSheet, (HashMap) columnMap.get(k + 1));
            }
            //  默認樣式。
            setStyle(cellStyle, font, fontSize);

            CellStyle cell_style = null;
            CellStyle row_style = null;
            CellStyle column_style = null;
            //  寫入小標題與數據。
            Integer SIZE = listRow.size() < MAX_ROWSUM ? listRow.size() : MAX_ROWSUM;
            Integer MAXSYTLE = listRow.size() < MAX_ROWSYTLE ? listRow.size() : MAX_ROWSYTLE;
            Map<Integer, Integer> sizeMap = new HashMap<>();

            sxssfSheet.setForceFormulaRecalculation(true);

            for (int i = 0; i < SIZE; i++) {
                sxssfRow = sxssfSheet.createRow(jRow);
                for (int j = 0; j < listRow.get(i).length; j++) {

                    //  樣式過多會導致GC內存溢出!
                    try {

                        Cell cell = null;
                        if (patternIsImg(String.valueOf(listRow.get(i)[j]))) {
                            cell = createCell(sxssfRow, j, " ");
                            drawPicture(wb, sxssfDrawing, String.valueOf(listRow.get(i)[j]), j, jRow);
                        } else {
                            cell = createCell(sxssfRow, j, String.valueOf(listRow.get(i)[j]));
                        }

                        /** ========== 單元格類型;設置對應格式 ========start== */
                        //BigDecimal 類型
                        if (BIGDECIMAL_CLASS.equals(listRow.get(i)[j].getClass().toString())) {
                            cell.setCellValue(Double.valueOf(String.valueOf(listRow.get(i)[j])));
                            XSSFDataFormat format = wb.getXSSFWorkbook().createDataFormat();
                            String defualtFmt = "_ * #,##0 ;_ * -#,##0 ;_ * \"-\"??_ ;_ @_ ";
                            switch (precision) {
                                case 1:
                                    defualtFmt = "_ * #,##0.0 ;_ * -#,##0.0 ;_ * \"-\"??_ ;_ @_ ";
                                    break;
                                case 2:
                                    defualtFmt = "_ * #,##0.00 ;_ * -#,##0.00 ;_ * \"-\"??_ ;_ @_ ";
                                    break;
                                case 3:
                                    defualtFmt = "_ * #,##0.000 ;_ * -#,##0.000 ;_ * \"-\"??_ ;_ @_ ";
                                    break;
                                case 4:
                                    defualtFmt = "_ * #,##0.0000 ;_ * -#,##0.0000 ;_ * \"-\"??_ ;_ @_ ";
                                    break;
                            }
                            cellStyle.setDataFormat(format.getFormat(defualtFmt));
                        }
                        /** ========== 單元格類型;設置對應格式 ========end== */

                        //設置單元格樣式
                        cell.setCellStyle(cellStyle);

                        /** ========== 設置公式 ========start== */
                        if (String.valueOf(listRow.get(i)[j]).indexOf(GS) != -1) {
                            String rowCell = String.valueOf(listRow.get(i)[j]).replace(GS, "");
                            cell.setCellFormula(rowCell);

                        }
                        /** ========== 設置公式 ========end== */


                        /** ========== 超鏈接設置 ========start== */
                        if (DOCUMENT.equals(linkType)) {
                            //設置超鏈接
                            if (Arrays.asList(sheetName).contains(listRow.get(i)[j])) {
                                for (int n = 1; n < sheetName.length; n++) {
                                    if (sheetName[n].equals(listRow.get(i)[j])) {
                                        CreationHelper createHelper = wb.getCreationHelper();
                                        XSSFHyperlink link = (XSSFHyperlink) createHelper.createHyperlink(HyperlinkType.DOCUMENT);
                                        link.setAddress("#'" + sheetName[n] + "'!A1");
                                        //設置超鏈接樣式
                                        XSSFCellStyle linkStyle = wb.getXSSFWorkbook().createCellStyle();
                                        XSSFFont cellFont = wb.getXSSFWorkbook().createFont();
                                        cellFont.setUnderline((byte) 1);
                                        cellFont.setColor(IndexedColors.fromInt(4).index);
                                        cellFont.setFontName("Arial");
                                        cellFont.setFontHeight(12);
                                        linkStyle.setAlignment(HorizontalAlignment.CENTER);
                                        linkStyle.setVerticalAlignment(VerticalAlignment.CENTER);
                                        linkStyle.setFont(cellFont);
                                        cell.setCellStyle(linkStyle);
                                        //超鏈接
                                        setBorder(linkStyle, true);
                                        cell.setHyperlink(link);
                                        break;
                                    }
                                }
                            }
                        }
                        /** ========== 超鏈接設置 ========start== */

                        //  自定義:每個表格每一列的樣式(看該方法說明)。
//                        if (columnStyles != null && jRow >= pane && i <= MAXSYTLE) {
                        if (columnStyles != null && i <= MAXSYTLE) {
                            setExcelRowStyles(cell, wb, sxssfRow, (List) columnStyles.get(k + 1), j);
                        }
                        //  自定義:每個表格每一行的樣式(看該方法說明)。
                        if (rowStyles != null && i <= MAXSYTLE) {
                            setExcelRowStyles(cell, wb, sxssfRow, (List) rowStyles.get(k + 1), jRow);
                        }

                        if (Arrays.asList(listRow.get(i)).contains("小計") || Arrays.asList(listRow.get(i)).contains("總計")) {
                            setTotalStyles(wb, cell);
                        }
                        // 自定義標題樣式
                        if (rowList != null && rowList.size() > 0) {
                            for (int rowListIndex = 0; rowListIndex < rowList.size(); rowListIndex++) {
                                if (rowList.get(rowListIndex) == i) {
                                    setSubTitleStyles(wb, cell, sxssfRow, slashMap);
                                }
                            }
                        } else {
                            if (i == 0) {
                                setSubTitleStyles(wb, cell, sxssfRow, slashMap);
                            }
                        }
                        //  自定義:每一個單元格樣式(看該方法說明)。
                        if (styles != null && i <= MAXSYTLE) {
                            setExcelStyles(cell, wb, sxssfRow, (List<List<Object[]>>) styles.get(k + 1), j, i);
                        }

                        //篩選單元格最大長度
                        if (sizeMap.get(j) != null && !CellType.FORMULA.equals(cell.getCellType())) {
//                            BigDecimal b = ((new BigDecimal(sizeMap.get(j)).add(new BigDecimal(listRow.get(i)[j].getBytes().length))).divide(new BigDecimal(2)).setScale(0, RoundingMode.HALF_UP));
//                            sizeMap.put(j, Integer.valueOf(String.valueOf(b)));
                            sizeMap.put(j, Math.max(sizeMap.get(j), String.valueOf(listRow.get(i)[j]).getBytes().length));
                        } else {
                            sizeMap.put(j, String.valueOf(listRow.get(i)[j]).getBytes().length);
                        }
                    } catch (Exception e) {
                        log.debug("=== ===  === :Andyczy ExcelUtils Exception Message:The maximum number of cell styles was exceeded. You can define up to 4000 styles!");
                    }
                }
                jRow++;
                sxssfSheet.setForceFormulaRecalculation(true);

            }

            //設置單元格長度, 這里要乘上256
            for (Integer i : sizeMap.keySet()) {
                sxssfSheet.setColumnWidth(i, (sizeMap.get(i) + 9) * 256);
            }
            k++;
            sxssfSheet.setForceFormulaRecalculation(true);
        }

    }

    private static boolean hasDouble(String s) {
        boolean bol = true;
        try {
            Double.valueOf(s);
        } catch (Exception e) {
            bol = false;
        }
        return bol;
    }


    /**
     * @param cell         Cell對象。
     * @param wb           SXSSFWorkbook對象。
     * @param fontSize     字體大小。
     * @param bold         是否加粗。
     * @param center       是否左右上下居中。
     * @param isBorder     是否忽略邊框
     * @param leftBoolean  左對齊
     * @param rightBoolean 右對齊
     * @param height       行高
     */
    public static void setExcelStyles(Cell cell, SXSSFWorkbook wb, SXSSFRow sxssfRow, Integer fontSize, Boolean bold, Boolean center, Boolean isBorder, Boolean leftBoolean,
                                      Boolean rightBoolean, Integer fontColor, Integer height) {
        CellStyle cellStyle = cell.getRow().getSheet().getWorkbook().createCellStyle();
        //保證了既可以新建一個CellStyle,又可以不丟失原來的CellStyle 的樣式
        cellStyle.cloneStyleFrom(cell.getCellStyle());
        //左右居中、上下居中
        if (center != null && center) {
            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        }
        //右對齊
        if (rightBoolean != null && rightBoolean) {
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            cellStyle.setAlignment(HorizontalAlignment.RIGHT);
        }
        //左對齊
        if (leftBoolean != null && leftBoolean) {
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            cellStyle.setAlignment(HorizontalAlignment.LEFT);
        }
        //是否忽略邊框
        if (isBorder != null && isBorder) {
            setBorderColor(cellStyle, isBorder);
        }
        //設置單元格字體樣式
        XSSFFont font = (XSSFFont) wb.createFont();
        if (bold != null && bold) {
            font.setBold(bold);
        }
        //行高
        if (height != null) {
            sxssfRow.setHeight((short) (height * 2));
        }
        font.setFontName("Arial");
        font.setFontHeight(fontSize == null ? 12 : fontSize);
        cellStyle.setFont(font);
        //   點擊可查看顏色對應的值: BLACK(8), WHITE(9), RED(10),
        font.setColor(IndexedColors.fromInt(fontColor == null ? 8 : fontColor).index);

        //金額右對齊
        if (BIGDECIMAL_CLASS.equals(sxssfRow.getClass().toString())) {
            cellStyle.setAlignment(HorizontalAlignment.RIGHT);
        }

        cell.setCellStyle(cellStyle);
    }

    public static void setExcelTitleStyles(Cell cell, SXSSFWorkbook wb, SXSSFRow sxssfRow, List<Object[]> rowstyleList, int rowIndex) {
        if (rowstyleList != null && rowstyleList.size() > 0) {
            Integer[] rowstyle = (Integer[]) rowstyleList.get(1);
            for (int i = 0; i < rowstyle.length; i++) {
                if (rowIndex == rowstyle[i]) {
                    Boolean[] bool = (Boolean[]) rowstyleList.get(0);
                    Integer fontColor = null;
                    Integer fontSize = null;
                    Integer height = null;
                    //當有設置顏色值 、字體大小、行高才獲取值
                    if (rowstyleList.size() >= 3) {
                        int leng = rowstyleList.get(2).length;
                        if (leng >= 1) {
                            fontColor = (Integer) rowstyleList.get(2)[0];
                        }
                        if (leng >= 2) {
                            fontSize = (Integer) rowstyleList.get(2)[1];
                        }
                        if (leng >= 3) {
                            height = (Integer) rowstyleList.get(2)[2];
                        }
                    }
                    setExcelStyles(cell, wb, sxssfRow, fontSize, Boolean.valueOf(bool[3]), Boolean.valueOf(bool[0]), Boolean.valueOf(bool[4]), Boolean.valueOf(bool[2]), Boolean.valueOf(bool[1]), fontColor, height);
                }
            }
        }
    }


    public static void setExcelRowStyles(Cell cell, SXSSFWorkbook wb, SXSSFRow sxssfRow, List<Object[]> rowstyleList, int rowIndex) {
        if (rowstyleList != null && rowstyleList.size() > 0) {
            Integer[] rowstyle = (Integer[]) rowstyleList.get(1);
            for (int i = 0; i < rowstyle.length; i++) {
                if (rowIndex == rowstyle[i]) {
                    Boolean[] bool = (Boolean[]) rowstyleList.get(0);
                    Integer fontColor = null;
                    Integer fontSize = null;
                    Integer height = null;
                    //當有設置顏色值 、字體大小、行高才獲取值
                    if (rowstyleList.size() >= 3) {
                        int leng = rowstyleList.get(2).length;
                        if (leng >= 1) {
                            fontColor = (Integer) rowstyleList.get(2)[0];
                        }
                        if (leng >= 2) {
                            fontSize = (Integer) rowstyleList.get(2)[1];
                        }
                        if (leng >= 3) {
                            height = (Integer) rowstyleList.get(2)[2];
                        }
                    }
                    setExcelStyles(cell, wb, sxssfRow, fontSize, Boolean.valueOf(bool[3]), Boolean.valueOf(bool[0]), Boolean.valueOf(bool[4]), Boolean.valueOf(bool[2]), Boolean.valueOf(bool[1]), fontColor, height);
                }
            }
        }
    }

    /**
     * 畫圖片
     * @param wb
     * @param sxssfSheet
     * @param pictureUrl
     * @param rowIndex
     */
    /**
     * 畫圖片
     *
     * @param wb
     * @param sxssfDrawing
     * @param pictureUrl
     * @param rowIndex
     */
    private static void drawPicture(SXSSFWorkbook wb, SXSSFDrawing sxssfDrawing, String pictureUrl, int colIndex, int rowIndex) {
        //rowIndex代表當前行
        try {
            if (pictureUrl != null) {
                URL url = new URL(pictureUrl);
                //打開鏈接
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5 * 1000);
                InputStream inStream = conn.getInputStream();
                byte[] data = readInputStream(inStream);
                //設置圖片大小,
                XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 50, 50, colIndex, rowIndex, colIndex + 1, rowIndex + 1);
                anchor.setAnchorType(DONT_MOVE_AND_RESIZE);
                sxssfDrawing.createPicture(anchor, wb.addPicture(data, XSSFWorkbook.PICTURE_TYPE_JPEG));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 是否是圖片
     *
     * @param str
     * @return
     */
    public static Boolean patternIsImg(String str) {
        String reg = ".+(.JPEG|.jpeg|.JPG|.jpg|.png|.gif)$";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(str);
        Boolean temp = matcher.find();
        return temp;
    }


    /**
     * @param inStream
     * @return
     * @throws Exception
     */
    private static byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        //創建一個Buffer字符串
        byte[] buffer = new byte[1024];
        //每次讀取的字符串長度,如果為-1,代表全部讀取完畢
        int len = 0;
        //使用一個輸入流從buffer里把數據讀取出來
        while ((len = inStream.read(buffer)) != -1) {
            //用輸出流往buffer里寫入數據,中間參數代表從哪個位置開始讀,len代表讀取的長度
            outStream.write(buffer, 0, len);
        }
        //關閉輸入流
        inStream.close();
        //把outStream里的數據寫入內存
        return outStream.toByteArray();
    }


    /**
     * 自定義:大標題
     *
     * @param jRow
     * @param k
     * @param wb
     * @param labelName
     * @param sxssfRow
     * @param sxssfSheet
     * @param listRow
     * @return
     */
    private static int setLabelName(Integer jRow, Integer k, SXSSFWorkbook wb, String[] labelName, SXSSFRow sxssfRow, SXSSFSheet sxssfSheet, List<Object[]> listRow) {

        if (labelName != null) {
            //  自定義:大標題和樣式。參數說明:new String[]{"表格數據一", "表格數據二", "表格數據三"}
            sxssfRow = sxssfSheet.createRow(0);
            Cell cell = createCell(sxssfRow, 0, labelName[k]);
            setMergedRegion(sxssfSheet, 0, 0, 0, listRow.get(0).length - 1);
            setLabelStyles(wb, cell, sxssfRow);
            jRow = 1;
        }
        return jRow;
    }

    /**
     * 設置數據:無樣式(行、列、單元格樣式)
     *
     * @param wb
     * @param sxssfRow
     * @param dataLists
     * @param regionMap
     * @param columnMap
     * @param paneMap
     * @param sheetName
     * @param labelName
     * @param dropDownMap
     * @throws Exception
     */
    public static void setDataListNoStyle(SXSSFWorkbook wb, SXSSFRow sxssfRow, List<List<Object[]>> dataLists, HashMap regionMap,
                                          HashMap columnMap, HashMap paneMap, String[] sheetName, String[] labelName, HashMap dropDownMap, Integer defaultColumnWidth, Integer fontSize, String linkType, Integer precision) throws Exception {
        if (dataLists == null) {
            log.debug("=== ===  === :Andyczy ExcelUtils Exception Message:Export data(type:List<List<String[]>>) cannot be empty!");
        }
        if (sheetName == null) {
            log.debug("=== ===  === :Andyczy ExcelUtils Exception Message:Export sheet(type:String[]) name cannot be empty!");
        }
        int k = 0;
        for (List<Object[]> listRow : dataLists) {
            SXSSFSheet sxssfSheet = wb.createSheet();
            sxssfSheet.setDefaultColumnWidth(defaultColumnWidth);
            wb.setSheetName(k, sheetName[k]);
            CellStyle cellStyle = wb.createCellStyle();
            XSSFFont font = (XSSFFont) wb.createFont();

            int jRow = 0;
            //  自定義:大標題(看該方法說明)。
            jRow = setLabelName(jRow, k, wb, labelName, sxssfRow, sxssfSheet, listRow);

            //  自定義:每個表格固定表頭(看該方法說明)。
            if (paneMap != null && paneMap.get(k + 1) != null) {
                createFreezePane(sxssfSheet, (ArrayList<Integer[]>) paneMap.get(k + 1));
            }
            //  自定義:每個單元格自定義合並單元格:對每個單元格自定義合並單元格(看該方法說明)。
            if (regionMap != null) {
                setMergedRegion(sxssfSheet, (ArrayList<Integer[]>) regionMap.get(k + 1));
            }
            //  自定義:每個單元格自定義下拉列表:對每個單元格自定義下拉列表(看該方法說明)。
            if (dropDownMap != null) {
                setDataValidation(sxssfSheet, (List<String[]>) dropDownMap.get(k + 1), listRow.size());
            }
            //  自定義:每個表格自定義列寬:對每個單元格自定義列寬(看該方法說明)。
            if (columnMap != null) {
                setColumnWidth(sxssfSheet, (HashMap) columnMap.get(k + 1));
            }
            //  默認樣式。
            setStyle(cellStyle, font, fontSize);


            //  寫入小標題與數據。
            Integer SIZE = listRow.size() < MAX_ROWSUM ? listRow.size() : MAX_ROWSUM;
            for (int i = 0; i < SIZE; i++) {
                sxssfRow = sxssfSheet.createRow(jRow);
                for (int j = 0; j < listRow.get(i).length; j++) {
                    Cell cell = createCell(sxssfRow, j, String.valueOf(listRow.get(i)[j]));
                    cell.setCellStyle(cellStyle);
                }
                jRow++;
            }
            k++;
        }
    }


    public static void writeAndColse(SXSSFWorkbook sxssfWorkbook, OutputStream outputStream) throws Exception {
        try {
            if (outputStream != null) {
                sxssfWorkbook.setForceFormulaRecalculation(true);// 執行公式
                sxssfWorkbook.write(outputStream);
                sxssfWorkbook.dispose();
                outputStream.flush();
                outputStream.close();
            }
        } catch (Exception e) {
            System.out.println(" Andyczy ExcelUtils Exception Message:Output stream is not empty !");
            e.getSuppressed();
        }
    }

    /**
     * 功能描述:所有自定義單元格樣式
     *
     * @param cell
     * @param wb
     * @param styles
     */
    public static void setExcelStyles(Cell cell, SXSSFWorkbook wb, SXSSFRow sxssfRow, List<List<Object[]>> styles, int cellIndex, int rowIndex) {
        if (styles != null) {
            for (int z = 0; z < styles.size(); z++) {
                List<Object[]> stylesList = styles.get(z);
                if (stylesList != null) {
                    //樣式
                    Boolean[] bool = (Boolean[]) stylesList.get(0);
                    //顏色和字體
                    Integer fontColor = null;
                    Integer fontSize = null;
                    Integer height = null;
                    //當有設置顏色值 、字體大小、行高才獲取值
                    if (stylesList.size() >= 2) {
                        int leng = stylesList.get(1).length;
                        if (leng >= 1) {
                            fontColor = (Integer) stylesList.get(1)[0];
                        }
                        if (leng >= 2) {
                            fontSize = (Integer) stylesList.get(1)[1];
                        }
                        if (leng >= 3) {
                            height = (Integer) stylesList.get(1)[2];
                        }
                    }
                    //第幾行第幾列
                    for (int m = 2; m < stylesList.size(); m++) {
                        Integer[] str = (Integer[]) stylesList.get(m);
                        if (cellIndex + 1 == (str[1]) && rowIndex + 1 == (str[0])) {
                            setExcelStyles(cell, wb, sxssfRow, fontSize, Boolean.valueOf(bool[3]), Boolean.valueOf(bool[0]), Boolean.valueOf(bool[4]), Boolean.valueOf(bool[2]), Boolean.valueOf(bool[1]), fontColor, height);
                        }
                    }
                }
            }
        }
    }


    /**
     * 大標題樣式
     *
     * @param wb
     * @param cell
     * @param sxssfRow
     */
    public static void setLabelStyles(SXSSFWorkbook wb, Cell cell, SXSSFRow sxssfRow) {
        CellStyle cellStyle = wb.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        sxssfRow.setHeight((short) (399 * 2));
        XSSFFont font = (XSSFFont) wb.createFont();
        font.setFontName("Arial");
        font.setFontHeight(14);
        font.setBold(true);
        cellStyle.setFont(font);
        cell.setCellStyle(cellStyle);
    }

    /**
     * 合計/小計 樣式
     *
     * @param wb
     * @param cell
     */
    public static void setTotalStyles(SXSSFWorkbook wb, Cell cell) {
        XSSFCellStyle cellStyle = wb.getXSSFWorkbook().createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        XSSFFont font = (XSSFFont) wb.createFont();
        font.setFontName("Arial");
        font.setFontHeight(12);
//        font.setColor(new XSSFColor(new java.awt.Color(221,235,247)));
        font.setBold(true);
        cellStyle.setFont(font);
        cellStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(189, 235, 247)));
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        setBorder(cellStyle, true);
        cell.setCellStyle(cellStyle);
    }

    /**
     * 小標題樣式
     *
     * @param wb
     * @param cell
     */
    public static void setSubTitleStyles(SXSSFWorkbook wb, Cell cell, SXSSFRow sxssfRow, HashMap slashMap) {
        XSSFCellStyle cellStyle = wb.getXSSFWorkbook().createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        if (slashMap != null) {
            sxssfRow.setHeight((short) (399 * 1.8));
        }
        XSSFFont font = (XSSFFont) wb.createFont();
        font.setFontName("Arial");
        font.setFontHeight(12);
        font.setColor(IndexedColors.WHITE.index);
        font.setBold(true);
        cellStyle.setFont(font);
        cellStyle.setFillForegroundColor(new XSSFColor(new java.awt.Color(47, 117, 181)));
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        setBorder(cellStyle, true);
        cell.setCellStyle(cellStyle);
    }

    /**
     * 默認樣式
     *
     * @param cellStyle
     * @param font
     * @return
     * @Parm
     */
    public static void setStyle(CellStyle cellStyle, XSSFFont font, Integer fontSize) {
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        font.setFontName("Arial");
        cellStyle.setFont(font);
        font.setFontHeight(fontSize);
        setBorder(cellStyle, true);
    }


    /**
     * 判斷字符串是否為空
     *
     * @param str
     * @return
     */
    public static boolean isBlank(String str) {
        int strLen;
        if (str != null && (strLen = str.length()) != 0) {
            for (int i = 0; i < strLen; ++i) {
                if (!Character.isWhitespace(str.charAt(i))) {
                    return false;
                }
            }
            return true;
        } else {
            return true;
        }
    }

    /**
     * 功能描述: 鎖定行(固定表頭)
     *
     * @param sxssfSheet
     * @param row
     */
    public static void createFreezePane(SXSSFSheet sxssfSheet, Integer row) {
        if (row != null && row > 0) {
            sxssfSheet.createFreezePane(0, row, 0, 1);
        }
    }

    /**
     * 功能描述: 鎖定行/列(固定表頭/列頭)
     *
     * @param sxssfSheet
     * @param rowColList
     */
    public static void createFreezePane(SXSSFSheet sxssfSheet, ArrayList<Integer[]> rowColList) {
        Optional.ofNullable(rowColList).filter(s -> s.size() > 0).ifPresent(s -> {
            for (int i = 0; i < rowColList.size(); i++) {
                Integer[] str = rowColList.get(i);
                if (str.length > 0 && str.length == 2) {
                    int colSplit = str[0]; //凍結的列數
                    int rowSplit = str[1]; //凍結的行數
//                    int leftmostColumn = str[2]; //首列可見序號
//                    int topRow = str[3]; //首行可見序號
                    // colSplit=凍結的列數、rowSplit=凍結的行數、leftmostColumn=首列序號、leftmostColumn=首行序號
                    // sxssfSheet.createFreezePane(colSplit, rowSplit, leftmostColumn, leftmostColumn);
                    sxssfSheet.createFreezePane(colSplit, rowSplit);
                }
            }
        });
    }

    /**
     * 功能描述: 設置斜線
     *
     * @param sxssfSheet
     * @param rowColList
     */
    public static void createSlash(SXSSFWorkbook wb, SXSSFSheet sxssfSheet, ArrayList<Integer[]> rowColList) {
        Optional.ofNullable(rowColList).filter(s -> s.size() > 0).ifPresent(s -> {
            for (int i = 0; i < rowColList.size(); i++) {
                Integer[] str = rowColList.get(i);
                if (str.length > 0 && str.length == 4) {

                    CreationHelper helper = wb.getCreationHelper();
                    XSSFDrawing drawing = sxssfSheet.getDrawingPatriarch();
                    ClientAnchor anchor = helper.createClientAnchor();
                    // 設置斜線的開始位置
                    anchor.setCol1(str[0]);
                    anchor.setRow1(str[1]);
                    // 設置斜線的結束位置
                    anchor.setCol2(str[2]);
                    anchor.setRow2(str[3]);
                    XSSFSimpleShape shape = drawing.createSimpleShape((XSSFClientAnchor) anchor);
                    // 設置形狀類型為線型
                    shape.setShapeType(ShapeTypes.LINE);
                    // 設置線寬
                    shape.setLineWidth(0.3);
                    // 設置線的風格
                    shape.setLineStyle(0);
                    // 設置線的顏色
                    shape.setLineStyleColor(00, 00, 00);
                }
            }
        });
    }

    public static void createFilter(SXSSFSheet sxssfSheet, HashMap dataFilter, Integer k) {
        Optional.ofNullable(dataFilter).filter(s -> s.size() > 0).ifPresent(s -> {
            String value = String.valueOf(s.get(k));
            if (StringUtils.isNotBlank(value)) {
                CellRangeAddress c = CellRangeAddress.valueOf(value);
                sxssfSheet.setAutoFilter(c);
            }
        });
    }

    /**
     * 功能描述: 自定義列寬
     *
     * @param sxssfSheet
     * @param map
     */
    public static void setColumnWidth(SXSSFSheet sxssfSheet, HashMap map) {
        if (map != null) {
            Iterator iterator = map.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry entry = (Map.Entry) iterator.next();
                Object key = entry.getKey();
                Object val = entry.getValue();
                sxssfSheet.setColumnWidth((int) key, (int) val * 512);
            }
        }
    }


    /**
     * 功能描述: excel 合並單元格
     *
     * @param sheet
     * @param rowColList
     */
    public static void setMergedRegion(SXSSFSheet sheet, ArrayList<Integer[]> rowColList) {
        if (rowColList != null && rowColList.size() > 0) {
            for (int i = 0; i < rowColList.size(); i++) {
                Integer[] str = rowColList.get(i);
                if (str.length > 0 && str.length == 4) {
                    Integer firstRow = str[0];
                    Integer lastRow = str[1];
                    Integer firstCol = str[2];
                    Integer lastCol = str[3];
                    setMergedRegion(sheet, firstRow, lastRow, firstCol, lastCol);
                }
            }
        }
    }

    /**
     * 功能描述: 合並單元格
     *
     * @param sheet
     * @param firstRow
     * @param lastRow
     * @param firstCol
     * @param lastCol
     */
    public static void setMergedRegion(SXSSFSheet sheet, int firstRow, int lastRow, int firstCol, int lastCol) {
        sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
    }


    /**
     * 功能描述:下拉列表
     *
     * @param sheet
     * @param dropDownListData
     * @param dataListSize
     */
    public static void setDataValidation(SXSSFSheet sheet, List<String[]> dropDownListData, int dataListSize) {
        if (dropDownListData.size() > 0) {
            for (int col = 0; col < dropDownListData.get(0).length; col++) {
                Integer colv = Integer.parseInt(dropDownListData.get(0)[col]);
                setDataValidation(sheet, dropDownListData.get(col + 1), 1, dataListSize < 100 ? 500 : dataListSize, colv, colv);
            }
        }
    }


    /**
     * 功能描述:下拉列表
     *
     * @param xssfWsheet
     * @param list
     * @param firstRow
     * @param lastRow
     * @param firstCol
     * @param lastCol
     */
    public static void setDataValidation(SXSSFSheet xssfWsheet, String[] list, Integer firstRow, Integer lastRow, Integer firstCol, Integer lastCol) {
        DataValidationHelper helper = xssfWsheet.getDataValidationHelper();
        CellRangeAddressList addressList = new CellRangeAddressList(firstRow, lastRow, firstCol, lastCol);
        DataValidationConstraint constraint = helper.createExplicitListConstraint(list);
        DataValidation dataValidation = helper.createValidation(constraint, addressList);
        dataValidation.createErrorBox(DataValidationError1, DataValidationError2);
        //  處理Excel兼容性問題
        if (dataValidation instanceof XSSFDataValidation) {
            dataValidation.setSuppressDropDownArrow(true);
            dataValidation.setShowErrorBox(true);
        } else {
            dataValidation.setSuppressDropDownArrow(false);
        }
        xssfWsheet.addValidationData(dataValidation);
    }

    /**
     * 功能描述:設置邊框
     *
     * @param cellStyle
     * @param isBorder
     */
    public static void setBorder(CellStyle cellStyle, Boolean isBorder) {
        if (isBorder) {
            cellStyle.setBorderBottom(BorderStyle.THIN);
            cellStyle.setBorderLeft(BorderStyle.THIN);
            cellStyle.setBorderTop(BorderStyle.THIN);
            cellStyle.setBorderRight(BorderStyle.THIN);
        } else {
            //添加白色背景,統一設置邊框后但不能選擇性去掉,只能通過背景覆蓋達到效果。
            cellStyle.setBottomBorderColor(IndexedColors.WHITE.getIndex());
            cellStyle.setLeftBorderColor(IndexedColors.WHITE.getIndex());
            cellStyle.setRightBorderColor(IndexedColors.WHITE.getIndex());
            cellStyle.setTopBorderColor(IndexedColors.WHITE.getIndex());
        }
    }

    public static void setBorderColor(CellStyle cellStyle, Boolean isBorder) {
        if (isBorder) {
            //添加白色背景,統一設置邊框后但不能選擇性去掉,只能通過背景覆蓋達到效果。
            cellStyle.setBottomBorderColor(IndexedColors.WHITE.getIndex());
            cellStyle.setLeftBorderColor(IndexedColors.WHITE.getIndex());
            cellStyle.setRightBorderColor(IndexedColors.WHITE.getIndex());
            cellStyle.setTopBorderColor(IndexedColors.WHITE.getIndex());
        }
    }


    /**
     * 驗證是否是日期
     *
     * @param strDate
     * @return
     */
    public static boolean verificationDate(String strDate, String style) {
        Date date = null;
        if (style == null) {
            style = "yyyy-MM-dd";
        }
        SimpleDateFormat formatter = new SimpleDateFormat(style);
        try {
            formatter.parse(strDate);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    public static String strToDateFormat(String strDate, String style, String expectDateFormatStr) {
        Date date = null;
        if (style == null) {
            style = "yyyy-MM-dd";
        }
        // 日期字符串轉成date類型
        SimpleDateFormat formatter = new SimpleDateFormat(style);
        try {
            date = formatter.parse(strDate);
        } catch (Exception e) {
            return null;
        }
        // 轉成指定的日期格式
        SimpleDateFormat sdf = new SimpleDateFormat(expectDateFormatStr == null ? style : expectDateFormatStr);
        String str = sdf.format(date);
        return str;
    }


}
View Code

  

  ExcelTools:

package com.xxx.common.excel;

import org.apache.poi.ss.util.CellReference;

import java.math.BigDecimal;
import java.util.List;

/**
 * @ProjectName: git-dev
 * @Package: com.jfa.common.utils
 * @ClassName: ExcelTools
 * @Author:
 * @Description: excel 工具類
 */

public class ExcelTools {

    /**
     * 設置公式
     *
     * @param col:        需轉化成對應字母的列號
     * @param startIndex: 開始計算行號/列號
     * @param endIndex:   結束計算行號/列號
     * @return: java.lang.String
     * @author:
     */
    public static String setFormula(Integer col, Integer startIndex, Integer endIndex) {
        String colString = CellReference.convertNumToColString(col);
        String formula = CommonsUtils.GS.concat("=SUM(" + colString + startIndex + ":" + colString + endIndex + ")");
        return formula;
    }

    /**
     * 設置公式
     *
     * @param startCol:   需轉化成對應字母的列號
     * @param endCol:     需轉化成對應字母的列號
     * @param startIndex: 開始計算行號/列號
     * @param endIndex:   結束計算行號/列號
     * @return: java.lang.String
     * @author:
     */
    public static String setFormula(Integer startCol, Integer endCol, Integer startIndex, Integer endIndex) {
        String startColString = CellReference.convertNumToColString(startCol);
        String endColString = CellReference.convertNumToColString(endCol);
        String formula = CommonsUtils.GS.concat("=SUM(" + startColString + startIndex + ":" + endColString + endIndex + ")");
        return formula;
    }

    /**
     * 設置公式
     *
     * @param col:       需轉化成對應字母的列號
     * @param indexList: 續統計的行號
     * @return: java.lang.String
     * @author:
     */
    public static String setFormula(Integer col, List<Integer> indexList) {
        String colString = CellReference.convertNumToColString(col);
        StringBuffer sb = new StringBuffer();
        if (indexList != null && indexList.size() > 0) {
            for (int n = 0; n < indexList.size(); n++) {
                sb.append(colString.concat(indexList.get(n).toString()));
                if (n < indexList.size() - 1) {
                    sb.append("+");
                }
            }
        }
        String formula = CommonsUtils.GS.concat("=SUM(" + sb.toString() + ")");
        return formula;
    }

    /**
     * 設置空字符串
     *
     * @param n:
     * @return: java.lang.String[]
     * @author:
     */
    public static void setEmpty(List<Object> list, int n) {
        for (int i = 0; i < n; i++) {
            list.add("");
        }
    }

    /**
     * 設置橫崗
     *
     * @param n:
     * @return: java.lang.String[]
     * @author:
     */
    public static void setBigDecimal(List<Object> list, int n) {
        for (int i = 0; i < n; i++) {
            list.add(BigDecimal.ZERO);
        }
    }

    /**
     * List轉String[]
     *
     * @param list:
     * @return: java.lang.String[]
     * @author:
     */
    public static Object[] list2ObjArr(List<Object> list) {
        Object[] strArr = new Object[list.size()];
        for (int i = 0; i < list.size(); i++) {
            strArr[i] = list.get(i);
        }
        return strArr;
    }

    /**
     * List轉String[]
     *
     * @param list:
     * @return: java.lang.String[]
     * @author:
     */
    public static String[] list2StrArr(List<Object> list) {
        String[] strArr = new String[list.size()];
        for (int i = 0; i < list.size(); i++) {
            strArr[i] = String.valueOf(list.get(i));
        }
        return strArr;
    }

    /**
     * List轉String[]
     *
     * @param list:
     * @return: java.lang.String[]
     * @author:
     */
    public static String[] list2StrArr2(List<String> list) {
        String[] strArr = new String[list.size()];
        for (int i = 0; i < list.size(); i++) {
            strArr[i] = String.valueOf(list.get(i));
        }
        return strArr;
    }

}
View Code

 

 

會持續更新,先發個粗糙版的

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM