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;


}


 

你可能感兴趣的:(windows,java)