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

 

 

会持续更新,先发个粗糙版的

 

posted @ 2021-09-30 10:29  姜饼攻城狮  阅读(739)  评论(3编辑  收藏  举报