• EasyExcel 简单导入/导出 Controller Demo


    1、导入EasyExcel依赖
            
           
           
                com.alibaba
                easyexcel
                3.0.5
           

    ————————————————
     

    import com.alibaba.excel.EasyExcel;
    import com.alibaba.excel.ExcelWriter;
    import com.alibaba.excel.support.ExcelTypeEnum;
    import com.alibaba.excel.write.metadata.WriteSheet;
    import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
    import com.google.common.collect.Lists;
    import org.springframework.beans.BeanUtils;
    import org.springframework.beans.BeansException;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    import org.springframework.web.multipart.MultipartFile;

    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    import java.net.URLEncoder;
    import java.util.ArrayList;
    import java.util.List;

    /**
     * @ClassName ExcelController
     * @Descripition EasyExcel导入/导出
     * @Author admin
     * @Date 2023/10/10 15:40
     */
    @RestController
    @RequestMapping("/excel/test")
    public class ExcelController {

        // Excel文件名称
        private static final String FILE_NAME = "订单列表test";

        //一个sheet装100w数据
        private static final Integer PER_SHEET_ROW_COUNT = 30;
        //每次查询20w数据,每次写入20w数据
        private static final Integer PER_WRITE_ROW_COUNT = 10;


        /**
         * 一、EasyExcel简单导入
         *
         * @param file
         * @throws IOException
         */
        @PostMapping("/import")
        public void importExcel(@RequestParam MultipartFile file) throws IOException {

            InputStream inputStream = file.getInputStream();

            List list = EasyExcel.read(inputStream)
                    .head(CustomerImportClass.class)
                    // 设置sheet,默认读取第一个
                    .sheet()
                    // 设置标题所在行数
                    .headRowNumber(1)
                    .doReadSync();

            for (CustomerImportClass customerImportClass : list) {
                System.out.println(customerImportClass);
            }

            System.out.println("【成功导入Excel数据】条数 : " + list.size());
        }


        /**
         * 二、EasyExcel简单导入
         * 1.1、单sheet导入(读)Excel
         * 1.2、分页(批次)查询数据循环写入Excel表格
         *
         * @param file
         * @throws IOException
         */
        @PostMapping("/importPage")
        public void importPage(@RequestParam MultipartFile file) throws IOException {

            InputStream inputStream = file.getInputStream();

            // 1.1、单sheet导入(读)Excel
            // 1.2、分页(批次)查询数据循环写入Excel表格
            EasyExcel.read(inputStream, new CustomListener())
                    // 设置sheet,默认读取第一个
                    .sheet()
                    // 设置标题所在行数
                    .headRowNumber(1)
                    .doRead();

        }


        /**
         * 三、EasyExcel简单导入
         * 1.1、多sheet导入(读)Excel
         * 1.2、分页(批次)查询数据循环写入Excel表格
         *
         * @param file
         * @throws IOException
         */
        @PostMapping("/importSheetPage")
        public void importSheetPage(@RequestParam MultipartFile file) throws IOException {

            InputStream inputStream = file.getInputStream();

            // 2.1、多sheet导入(写入)Excel
            // 2.2、分页(批次)查询数据循环写入Excel表格
            EasyExcel.read(inputStream, new CustomListener())
                    // 设置标题所在行数
                    .headRowNumber(1)
                    .doReadAll();

        }


        /**
         * 一、EasyExcel简单导出
         *
         * @param response
         */
        @GetMapping("/export")
        public void exportExcel(HttpServletResponse response) {
            try {
                // 设置响应结果
                this.setExcelResponseProp(response, FILE_NAME);

                // 模拟业务代码,获取数据集
                List list = this.queryToExcel();

                EasyExcel.write(response.getOutputStream())
                        .head(ExcelTemplate.class)
                        .excelType(ExcelTypeEnum.XLSX)
                        .sheet(FILE_NAME)
                        .doWrite(list);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }


        /**
         * 二、EasyExcel简单批量导出
         * 1、单sheet导出(写入)Excel
         * 2、分页(批次)查询数据循环写入Excel表格
         *
         * @param response
         */
        @GetMapping("/exportPage")
        public void exportPage(HttpServletResponse response) {
            try {

                // 设置响应结果
                this.setExcelResponseProp(response, FILE_NAME);

                // 单sheet导出(写入)Excel
                exportSheet(response);

            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }


        /**
         * 三、EasyExcel简单批量导出
         * 1、多sheet导出(写入)Excel
         * 2、分页(批次)查询数据循环写入Excel表格
         *
         * @param response
         */
        @GetMapping("/exportSheetPage")
        public void exportSheetPage(HttpServletResponse response) {
            try {

                // 设置响应结果
                this.setExcelResponseProp(response, FILE_NAME);

                // 多sheet分页(批)查询数据循环写入Excel表格
                exportMoreSheet(response);

            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }


        /**
         * 设置响应结果
         *
         * @param response    响应结果对象
         * @param rawFileName 文件名
         * @throws UnsupportedEncodingException 不支持编码异常
         */
        private void setExcelResponseProp(HttpServletResponse response, String rawFileName) throws UnsupportedEncodingException {

            // 下载EXCEL
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");

            // 这里URLEncoder.encode可以防止浏览器端导出excel文件名中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode(rawFileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        }

        /**
         * easyExcel 导出Excel表格简单 : Demo
         */
        public void excelWriteUtil() {
            //1、创建一个文件对象
            File excelFile = new File("D:\\test\\test001\\desktop\\excel_test1001.xlsx");
            //2、判断文件是否存在,不存在则创建一个Excel文件
            if (!excelFile.exists()) {
                try {
                    excelFile.createNewFile();//创建一个新的文件
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //3、指定需要那个class去写。然后写到第一个sheet,名字为模版,然后文件流会自动关闭
            EasyExcel.write(excelFile, ExcelTemplate.class).sheet("订单模版").doWrite(queryToExcel());
        }


        /**
         * 1、查询数据库获取导出的数据集合
         * 2、集合转换导出模版实体集合:ExcelTemplate
         *
         * @return
         */
        public List queryToExcel() {
            // 1、查询数据库获取导出的数据集合
            // 模拟业务代码,获取数据集
            List orders = Lists.newArrayList();
            for (int i = 0; i < 115; i++) {
                ExcelTemplate template1 = new ExcelTemplate(1000L + i, "订单01" + i, "商品名称" + i, "sk1001" + i, 36L + i, 50L + i, "收件人" + i, "北京科技园" + i);
                orders.add(template1);
            }

            // 2、集合转换导出模版实体集合:ExcelTemplate
            List excels = new ArrayList<>();
            //遍历数据集,导出Excel
            for (int i = 0; i < orders.size(); i++) {
                ExcelTemplate order = orders.get(i);
                ExcelTemplate data = new ExcelTemplate();
                data.setOrderNum(order.getOrderNum());
                data.setOrderName(order.getOrderName());
                data.setGoodsName(order.getGoodsName());
                data.setGoodsNum(order.getGoodsNum());
                data.setPrice(order.getPrice());
                data.setNum(order.getNum());
                data.setUserName(order.getUserName());
                data.setAddress(order.getAddress());
                excels.add(data);
            }
            return excels;
        }


        /**
         * EasyExcel简单批量导出
         * 1、单sheet导出(写入)Excel
         * 2、分页(批次)查询数据循环写入Excel表格
         *
         * @param response
         * @throws IOException
         */
        public void exportSheet(HttpServletResponse response) throws IOException {
            OutputStream outputStream = null;
            try {
                //记录总数:实际中需要根据查询条件进行统计即可
                Integer totalCount = queryToExcel().size();
                //每次写入的数据量20w,每页查询20W
                Integer writeDataRows = PER_WRITE_ROW_COUNT;
                //计算sheet需要写入的次数
                Integer lastSheetWriteCount = totalCount % writeDataRows == 0 ? totalCount / writeDataRows : (totalCount / writeDataRows + 1);

                // ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                // HttpServletResponse response = requestAttributes.getResponse();

                outputStream = response.getOutputStream();
                //必须放到循环外,否则会刷新流
                ExcelWriter excelWriter = EasyExcel.write(outputStream).build();

                //创建Sheet
                // WriteSheet sheet = new WriteSheet();
                // sheet.setSheetName("测试Sheet001");
                // sheet.setSheetNo(0);
                //循环写入次数: j的自增条件是当不是最后一个Sheet的时候写入次数为正常的每个Sheet写入的次数,如果是最后一个就需要使用计算的次数lastSheetWriteCount
                for (int j = 0; j < lastSheetWriteCount; j++) {
                    //分页查询一次20w
                    List list = Lists.newArrayList();

                    // 集合截取起始下标计算
                    int startIndex = j * writeDataRows;

                    // 判断是否是最后一次写入Excel
                    if (j < (lastSheetWriteCount - 1)) {
                        list = queryToExcel().subList(startIndex, writeDataRows * (j + 1));
                    }
                    // 判断是否是最后一次写入Excel
                    if (j == (lastSheetWriteCount - 1)) {
                        // 计算是否是最后一次截取集合
                        int stepValue = queryToExcel().size() - (startIndex) >= writeDataRows ? writeDataRows : queryToExcel().size() - (startIndex);

                        list = queryToExcel().subList(startIndex, startIndex + stepValue);
                    }
                    // Page page = empMapper.selectPage(new Page(j + 1 + oneSheetWriteCount * i, writeDataRows), null);
                    // List empList = page.getRecords();
                    List empVoList = new ArrayList<>();
                    for (ExcelTemplate emp : list) {
                        ExcelTemplate empVo = new ExcelTemplate();
                        BeanUtils.copyProperties(emp, empVo);
                        empVoList.add(empVo);
                    }

                    WriteSheet writeSheet = EasyExcel.writerSheet(0, FILE_NAME).head(ExcelTemplate.class)
                            .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();

                    //写数据
                    excelWriter.write(empVoList, writeSheet);
                }

                /*// 下载EXCEL
                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                response.setCharacterEncoding("utf-8");
                // 这里URLEncoder.encode可以防止浏览器端导出excel文件名中文乱码 当然和easyexcel没有关系
                String fileName = URLEncoder.encode("员工信息", "UTF-8").replaceAll("\\+", "%20");
                response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");*/

                excelWriter.finish();
                outputStream.flush();

            } catch (IOException e) {
                e.printStackTrace();
            } catch (BeansException e) {
                e.printStackTrace();
            } finally {
                if (outputStream != null) {
                    outputStream.close();
                }
            }
        }


        /**
         * EasyExcel简单批量导出
         * 1、多sheet导出(写入)Excel
         * 2、分页(批次)查询数据循环写入Excel表格
         *
         * @param response
         * @throws IOException
         */
        public void exportMoreSheet(HttpServletResponse response) throws IOException {
            OutputStream outputStream = null;
            try {
                //记录总数:实际中需要根据查询条件进行统计即可
                Integer totalCount = queryToExcel().size();
                //每一个Sheet存放100w条数据
                Integer sheetDataRows = PER_SHEET_ROW_COUNT;
                //每次写入的数据量20w,每页查询20W
                Integer writeDataRows = PER_WRITE_ROW_COUNT;
                //计算需要的Sheet数量
                Integer sheetNum = totalCount % sheetDataRows == 0 ? (totalCount / sheetDataRows) : (totalCount / sheetDataRows + 1);
                //计算一般情况下每一个Sheet需要写入的次数(一般情况不包含最后一个sheet,因为最后一个sheet不确定会写入多少条数据)
                Integer oneSheetWriteCount = sheetDataRows / writeDataRows;
                //计算最后一个sheet需要写入的次数
                Integer lastSheetWriteCount = totalCount % sheetDataRows == 0 ? oneSheetWriteCount : (totalCount % sheetDataRows % writeDataRows == 0 ? (totalCount % sheetDataRows / writeDataRows) : (totalCount % sheetDataRows / writeDataRows + 1));

                // 获取响应 response
                // ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                // HttpServletResponse response = requestAttributes.getResponse();

                // 获取输出流
                outputStream = response.getOutputStream();
                //必须放到循环外,否则会刷新流
                ExcelWriter excelWriter = EasyExcel.write(outputStream).build();

                //开始分批查询分次写入
                for (int i = 0; i < sheetNum; i++) {
                    //创建Sheet
                    WriteSheet sheet = new WriteSheet();
                    sheet.setSheetName("测试Sheet001" + i);
                    sheet.setSheetNo(i);
                    //循环写入次数: j的自增条件是当不是最后一个Sheet的时候写入次数为正常的每个Sheet写入的次数,如果是最后一个就需要使用计算的次数lastSheetWriteCount
                    for (int j = 0; j < (i != sheetNum - 1 ? oneSheetWriteCount : lastSheetWriteCount); j++) {
                        //分页查询一次20w
                        List list = queryToExcel().subList(j * writeDataRows, writeDataRows * (j + 1));
                        if (i > 0) {
                            // 集合截取起始下标计算
                            int startIndex = i * sheetDataRows + writeDataRows * j;

                            // 计算是否是最后一次截取集合
                            int stepValue = queryToExcel().size() - (startIndex) >= writeDataRows ? writeDataRows : queryToExcel().size() - (startIndex);

                            list = queryToExcel().subList(startIndex, startIndex + stepValue);
                        }
                        // Page page = empMapper.selectPage(new Page(j + 1 + oneSheetWriteCount * i, writeDataRows), null);
                        // List empList = page.getRecords();
                        List empVoList = new ArrayList<>();
                        for (ExcelTemplate emp : list) {
                            ExcelTemplate empVo = new ExcelTemplate();
                            BeanUtils.copyProperties(emp, empVo);
                            empVoList.add(empVo);
                        }
                        WriteSheet writeSheet = EasyExcel.writerSheet(i, FILE_NAME + (i + 1)).head(ExcelTemplate.class)
                                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
                        //写数据
                        excelWriter.write(empVoList, writeSheet);
                    }
                }

                /*// 下载EXCEL
                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                response.setCharacterEncoding("utf-8");
                // 这里URLEncoder.encode可以防止浏览器端导出excel文件名中文乱码 当然和easyexcel没有关系
                String fileName = URLEncoder.encode("员工信息", "UTF-8").replaceAll("\\+", "%20");
                response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");*/

                excelWriter.finish();
                outputStream.flush();

            } catch (IOException e) {
                e.printStackTrace();
            } catch (BeansException e) {
                e.printStackTrace();
            } finally {
                if (outputStream != null) {
                    outputStream.close();
                }
            }
        }

    }

    import com.alibaba.excel.annotation.ExcelProperty;
    import lombok.Data;

    /**
     * @ClassName CustomerImportClass
     * @Descripition 导入模版类
     * @Author admin
     * @Date 2023/10/10 15:44
     */
    @Data
    public class CustomerImportClass {

        @ExcelProperty(index = 0)
        private String column1;

        @ExcelProperty(index = 1)
        private String column2;

        @ExcelProperty(index = 2)
        private String column3;

        @ExcelProperty(index = 3)
        private String column4;

        @ExcelProperty(index = 4)
        private String column6;

        @ExcelProperty(index = 5)
        private String column5;

        @ExcelProperty(index = 6)
        private String column7;
    }

    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.event.AnalysisEventListener;
    import com.alibaba.fastjson.JSON;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.compress.utils.Lists;

    import java.util.List;
    import java.util.Map;

    /**
     * @ClassName CustomListener
     * @Descripition 导入Excel监听解析表格数据
     * @Author admin
     * @Date 2023/10/9 15:40
     */
    @Slf4j
    public class CustomListener extends AnalysisEventListener> {

        // 处理数据: 分批导入阈值
        private static final Long size = 8L;

        // private List> list = Lists.newArrayList();
        private List list = Lists.newArrayList();

        //获取excel表头信息
        @Override
        public void invokeHeadMap(Map headMap, AnalysisContext context) {
            log.info("获取excel表头信息 data : {}", JSON.toJSONString(headMap));
            System.out.println(JSON.toJSONString(headMap));
            System.out.println();
            System.out.println();
        }

        // 每解析一行数据,该方法会被调用一次
        @Override
        public void invoke(Map map, AnalysisContext analysisContext) {
            log.info("Excel每解析一行数据,该方法(invoke)会被调用一次 data : {}", JSON.toJSONString(map));
            // int size = analysisContext.readRowHolder().getCellMap().entrySet().size();
            // System.out.println(size);

            list.add(map);
            if(list.size() >= CustomListener.size){
                for (Object o1 : list) {
                    System.out.println(o1);
                }
                System.out.println("处理数据: 分批导入阈值: " + size);
                System.out.println();
                System.out.println();
                list.clear();
            }
        }

        // 全部解析完成被调用
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {

            System.out.println("最后剩余数据;不够分割 长度 : " + list.size());
            if(CollectionUtils.isNotEmpty(list)){
                for (Object o : list) {
                    System.out.println(o);
                }
                System.out.println();
                list.clear();
            }
            System.out.println("解析数据完成!!!");
            // System.out.println("解析数据完成!!!");
        }
    }

    import com.alibaba.excel.annotation.ExcelProperty;
    import com.alibaba.excel.annotation.write.style.*;
    import com.alibaba.excel.enums.poi.BorderStyleEnum;
    import com.alibaba.excel.enums.poi.HorizontalAlignmentEnum;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;

    /**
     * @ClassName ExcelTemplate
     * @Descripition 导出模版
     * @Author admin
     * @Date 2023/10/9 18:14
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @HeadRowHeight(value = 50) // 头部行高
    @ContentRowHeight(value = 25) // 内容行高
    @ColumnWidth(value = 25) // 列宽
    // 头背景设置成红色 IndexedColors.RED.getIndex()
    // @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 10)
    // 头字体设置成20, 字体默认宋体
    @HeadFontStyle(fontName = "仿宋", fontHeightInPoints = 20)
    // 头部边框实线
    @HeadStyle(borderTop = BorderStyleEnum.THICK,
            borderBottom = BorderStyleEnum.THICK,
            borderLeft = BorderStyleEnum.THICK,
            borderRight = BorderStyleEnum.THICK)
    // 内容的背景设置成绿色  IndexedColors.GREEN.getIndex()
    // @ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 17)
    // 内容字体设置成20, 字体默认宋体
    @ContentFontStyle(fontName = "楷体", fontHeightInPoints = 20)
    // Excel设置内容字体是否水平居中、边框实线
    @ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.CENTER,
            borderTop = BorderStyleEnum.MEDIUM,
            borderBottom = BorderStyleEnum.MEDIUM,
            borderLeft = BorderStyleEnum.DOUBLE,
            borderRight = BorderStyleEnum.DOUBLE)
    public class ExcelTemplate {


        // 字符串的头背景设置成粉红 IndexedColors.PINK.getIndex()
        // @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 14)
        // 字符串的头字体设置成20
        // @HeadFontStyle(fontHeightInPoints = 20)
        // 字符串的内容背景设置成天蓝 IndexedColors.SKY_BLUE.getIndex()
        // @ContentStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 40)
        // 字符串的内容字体设置成20,默认宋体
        // @ContentFontStyle(fontName = "宋体", fontHeightInPoints = 20)
        // 设置是否水平居中
        // @ContentStyle(horizontalAlignment = HorizontalAlignmentEnum.LEFT)
        @ExcelProperty("订单编码")
        private Long orderNum;

        @ExcelProperty("订单名称")
        private String orderName;

        @ExcelProperty("商品名称")
        private String goodsName;

        @ExcelProperty("商品编码")
        private String goodsNum;

        @ExcelProperty("价格")
        private Long price;

        @ExcelProperty("数量")
        private Long num;

        @ExcelProperty("用户名称")
        private String userName;

        @ColumnWidth(value = 80) // 列宽
        @ExcelProperty("收货地址")
        private String address;


    }


     

  • 相关阅读:
    与所有 ARM 工具、软件兼容?韦斯佰瑞这款MCU内核值得关注!
    Qt第六十四章:QSplitter(分离部件)的使用
    基础IO(下)——Linux
    阿里开源数据同步神器DataX异构数据源间数据同步同步MySQL与HDFS相互实战
    41-MybatisPlus
    亚马逊卖家测评为什么一定要掌握自养号技巧
    java计算机毕业设计化妆品销售网站源码+mysql数据库+系统+lw文档+部署
    【JavaWeb】注册页面验证码,用户名已存在,密码格式校验
    redis 支持的数据类型
    C语言第三十弹---自定义类型:结构体(上)
  • 原文地址:https://blog.csdn.net/java_2017_csdn/article/details/133769762