欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Excel工具类-导出

程序员文章站 2024-02-24 13:07:46
...

使用前需要导出以下依赖:

	<!-- poi支持xls格式的excel文件 -->
	<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.17</version>
    </dependency>
    <!-- 让poi支持xlsx格式的excel文件 -->
    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>3.17</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas -->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml-schemas</artifactId>
      <version>3.17</version>
    </dependency>

excel工具类-导出 代码如下:

package cn.com.hellfs.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Excel工具类-导出
 * 使用顺序:getDownLoadWorkBook -> logicData -> setDownLoadResponse -> downLoad
 * @author HELLFS
 * @createDate 2021-06-11
 */
@Component
public class ExcelUtil {

    private Logger logger = LoggerFactory.getLogger(ExcelUtil.class);

    @Autowired
    DefaultLogicData defaultLogicData;

    /**
     * 获取作用于导出的Workbook对象
     * @param fileName      文件名(包含文件后缀名,例:excel模板.xlsx)
     * @param filePath      文件路径(不包含文件名,例:c:\excel\)
     *                          注意:路径分隔符在linux和windows下的区别;
     *                              为null,代码生成excel文件,填充数据;
     *                              不为null,读入excel模板文件,填充数据
     * @return  Workbook
     */
    public Workbook getDownLoadWorkBook(String fileName,String filePath){
        File file = null;
        if(StringUtils.isNotEmpty(filePath)){
            String fileUrl = filePath + fileName;
            logger.info("excel文件路径:{}",fileUrl);
            file = new File(fileUrl);
            if(!file.exists()){
                logger.info("指定的excel文件不存在!");
            }
        }

        Workbook workbook = null;

        if(fileName.endsWith(".xlsx")){
            if(file == null){
                workbook = new XSSFWorkbook();
            }else{
                try {
                    workbook = new XSSFWorkbook(new FileInputStream(file));
                } catch (IOException e) {
                    logger.error("读取excel文件失败,原因:{}",e);
                }
            }
        }else if(fileName.endsWith(".xls")){
            if(file == null){
                workbook = new HSSFWorkbook();
            }else{
                try {
                    workbook = new HSSFWorkbook(new FileInputStream(file));
                } catch (IOException e) {
                    logger.error("读取excel文件失败,原因:{}",e);
                }
            }
        }else{
            logger.info("其他excel文件格式,暂不支持;如需支持,请自行开发");
        }
        return workbook;
    }

    /**
     * excel数据处理逻辑
     *  使用方法:
     *      默认处理:logicData(workbook,null,params)
     *      自定义处理:以下方式任选其一
     *      logicData(workbook,new ExcelUtil.LogicData(){
     *         @Override
     *         public void logicData(Workbook workbook, Object... params) {
     *              //...处理逻辑
     *         }
     *      },params)
     *      或者
     *      logicData(workbook,(Workbook workbook, Object... params) -> {
     *         //...处理逻辑
     *      },params)
     *      注意:LogicExcel方法的params参数对应LogicData接口中logic方法的params参数
     * @param workbook      excel对象
     * @param logicData     处理逻辑接口,为null,则默认处理;不为null,则自定义处理
     *                          默认处理:参数列表个数为1,参数类型:Map<String,Map<List<String>,List<Object[]>>>
     *                              泛型解释:外层key:sheet页名,内层key:列名,内层value:数据
     *                          自定义处理:实现LogicData接口
     * @param params        参数列表(用于处理逻辑相关参数)
     */
    public void logicData(Workbook workbook,LogicData logicData,Object... params){
        if(logicData != null){
            logicData.logicData(workbook, params);
        }else{
            defaultLogicData.logicData(workbook, params);
        }
    }

    /**
     * 设置下载时的响应头,使得文件存在浏览器设置的下载位置
     * @param response      响应对象
     * @param fileName      文件名(包含文件后缀名)
     */
    public void setDownLoadResponse(HttpServletResponse response,String fileName){
        try {
            response.setContentType("application/ms-excel;charset=UTF-8");
            response.setHeader("Content-Disposition",
                    "attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName,"UTF-8"))));
        } catch (UnsupportedEncodingException e) {
            logger.error("设置响应头报错,原因:{}",e);
        }
    }

    /**
     * 下载
     * @param workbook      excel对象
     * @param response      响应对象
     * @param fileName      文件名(包含文件后缀名)
     */
    public void downLoad(Workbook workbook,HttpServletResponse response,String fileName){
        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
        } catch (IOException e) {
            logger.error("获取输出流失败,原因:{}",e);
        }

        try {
            workbook.write(outputStream);
            logger.info("导出" + fileName + "成功");
        } catch (IOException e) {
            logger.error("导出" + fileName + "失败");
        } finally {
            try {
                if(workbook != null){
                    workbook.close();
                }
                if(outputStream != null){
                    outputStream.flush();
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * excel处理逻辑接口
     */
    public interface LogicData{
        /**
         * 处理逻辑方法
         * @param workbook     excel对象
         * @param params       参数列表
         */
        void logicData(Workbook workbook,Object... params);
    }

    /**
     * 默认处理逻辑类
     */
    @Component
    public class DefaultLogicData implements LogicData{

        /**
         * 默认处理逻辑
         * @param workbook     excel对象
         * @param params       参数列表,参数列表个数为1,参数类型:Map<String,Map<List<String>,List<Object[]>>>
         *                          泛型解释:外层key:sheet页名,内层key:列名,内层value:数据
         */
        @Override
        public void logicData(Workbook workbook, Object... params) {
            //校验参数
            checkParams(params);

            Map<String, Map<List<String>, List<Object[]>>> map = 
                    (Map<String, Map<List<String>, List<Object[]>>>) params[0];

            for (String sheetName : map.keySet()) {
                Sheet sheet = workbook.createSheet(sheetName);
                Map<List<String>, List<Object[]>> titlesAndData = map.get(sheetName);
                Row rowByTitle = sheet.createRow(0);
                List<List<String>> titleList = new ArrayList<>(titlesAndData.keySet());

                //添加标题
                List<String> titles = titleList.get(0);
                for (int i = 0; i < titles.size(); i++) {
                    Cell cell = rowByTitle.createCell(i);
                    cell.setCellValue(titles.get(i));
                }

                //添加数据
                List<Object[]> datas = titlesAndData.get(titles);
                for (int i = 1; i < datas.size(); i++) {
                    Row rowByData = sheet.createRow(i);
                    Object[] data = datas.get(i - 1);
                    for (int j = 0; j < data.length; j++) {
                        Cell cell = rowByData.createCell(j);
                        cell.setCellValue(data[j].toString());
                    }
                }
            }
        }

        /**
         * 校验参数
         * @param params    参数列表
         */
        private void checkParams(Object... params){
            //长度判断
            if(params.length != 1){
                throw new RuntimeException("Parameter length greater than 1");
            }

            //参数类型校验
            if(params[0] instanceof Map){
                Map<Object, Object> map = (Map<Object, Object>) params[0];
                map.forEach((key,value) -> {
                    if(!(key instanceof String)){
                        throw new RuntimeException("The key data type of Map should be String");
                    }
                    
                    if(!(value instanceof Map)){
                        throw new RuntimeException("The Value data type of Map should be Map");
                    }
                    Map<Object, Object> valueByMap = (Map<Object, Object>) value;
                    valueByMap.forEach((nKey,nValue) -> {
                        if(!(nKey instanceof List)){
                            throw new RuntimeException("The key data type of inner Map should be List");
                        }
                        List<Object> nKeyList = (List<Object>) nKey;
                        if(!(nKeyList.get(0) instanceof String)){
                            throw new RuntimeException("The key data type of inner Map should be List<String>");
                        }
                        if(!(nValue instanceof List)){
                            throw new RuntimeException("The Value data type of inner Map should be List");
                        }
                        List<Object> nValueList = (List<Object>) nValue;
                        if(!(nValueList.get(0) instanceof Object[])){
                            throw new RuntimeException("The Value data type of inner Map should be List<Object[]>");
                        }
                    });
                });
            }else{
                throw new RuntimeException("The 'params[0]' data type should be map");
            }

        }
    }
}