首页 > 其他分享 >使用EasyExcel实现excel文件导入导出(附实战)

使用EasyExcel实现excel文件导入导出(附实战)

时间:2024-12-02 11:31:54浏览次数:8  
标签:存储 String EasyExcel excel private 导入 public

什么是EasyExcel

EasyExcel是一个由阿里巴巴开源的Java库,专注于处理大数据量的Excel文件读写操作。它以高性能、低内存占用和简单易用著称,特别适合处理大规模数据。EasyExcel通过异步处理和NIO技术优化了读写性能,同时提供了丰富的API和注解支持,使得数据导入导出变得简单快捷。

怎么使用EasyExcel

导入依赖

        <!-- https://github.com/alibaba/easyexcel -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.1.1</version>
        </dependency>

导入excel示例

被导入的实体类
@Getter
@Setter
@EqualsAndHashCode
public class DemoData {
    private String string;
    private Date date;
    private Double doubleData;
}
监听器
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class DemoDataListener implements ReadListener<DemoData> {

    /**
     * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据
     */
    private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private DemoDAO demoDAO;

    public DemoDataListener() {
        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
        demoDAO = new DemoDAO();
    }

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param demoDAO
     */
    public DemoDataListener(DemoDAO demoDAO) {
        this.demoDAO = demoDAO;
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(DemoData data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        cachedDataList.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
        demoDAO.save(cachedDataList);
        log.info("存储数据库成功!");
    }
}
代码
    /**
     * 指定列的下标或者列名
     *
     * <p>1. 创建excel对应的实体对象,并使用{@link ExcelProperty}注解. 参照{@link IndexOrNameData}
     * <p>2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link IndexOrNameDataListener}
     * <p>3. 直接读即可
     */
    @Test
    public void indexOrNameRead() {
        String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
        // 这里默认读取第一个sheet
        EasyExcel.read(fileName, IndexOrNameData.class, new IndexOrNameDataListener()).sheet().doRead();
    }

导出excel示例

被导出的实体类
@Getter
@Setter
@EqualsAndHashCode
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}
代码
    /**
     * 文件下载(失败了会返回一个有部分数据的Excel)
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link DownloadData}
     * <p>
     * 2. 设置返回的 参数
     * <p>
     * 3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
     */
    @GetMapping("download")
    public void download(HttpServletResponse response) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
    }

EasyExcel实战

实战背景

双选系统,管理员在双选开始前从excel导入学生和导师信息,在双选结束后导出学生和导师的匹配信息到excel

excel导入(以导入学生为例)

被导入的实体类
/**
 * excel学生导入对象
 *
 * @author hrh
 * 
 */
@Data
public class StudentExcelImport implements Serializable {

    /**
     * 学生学号
     */
    private String studentaccount;

    /**
     * 学生姓名
     */
    private String studentname;

    /**
     * 学生班级
     */
    private String studentclass;

    /**
     * 学生学院
     */
    private String studentcollege;

    /**
     * 性别
     */
    private String gender;


    private static final long serialVersionUID = 1L;
}
监听器

@Slf4j
public class StudentDataListener extends AnalysisEventListener<StudentExcelImport> {

    /**
     * 每隔100条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据
     */
    private List<StudentExcelImport> studentExcelList = new ArrayList<>(BATCH_COUNT);
    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private StudentService studentService;

    public StudentDataListener() {
        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
        // studentService = new StudentService();
    }

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param studentService
     */
    public StudentDataListener(StudentService studentService) {
        this.studentService = studentService;
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(StudentExcelImport data, AnalysisContext context) {
        studentExcelList.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (studentExcelList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            studentExcelList = new ArrayList<>(BATCH_COUNT);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     *
     * @return
     */
    private BaseResponse saveData() {
        if (CollectionUtils.isEmpty(studentExcelList)) {
            return ResultUtils.error(OPERATION_ERROR, "导入失败");
        }
        log.info("{}条数据,开始存储数据库!", studentExcelList.size());
        studentService.importStudentsFromExcel(studentExcelList);
        log.info("存储数据库成功!");
        return null;
    }
}
Controller层代码
    /**
     * 管理员从excel导入学生
     * @param file
     * @return
     */
    @PostMapping("/student/import-students")
    @ApiOperation(value = "管理员从excel批量导入学生")
    public BaseResponse<String> importStudents(@RequestParam("file") MultipartFile file) {
        try {
            EasyExcel.read(file.getInputStream(), StudentExcelImport.class, new StudentDataListener(studentService)).sheet().doRead();
            return ResultUtils.success("导入成功");
        } catch (Exception e) {
            e.printStackTrace();
            return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "导入失败");
        }
    }

excel导出

被导出的实体类
/**
 * 管理员导出匹配结果实体类
 * @author hrh
 */
@Data
public class MatchRecordQueryVO implements Serializable {

    /**
     * 学生学号
     */
    private String studentaccount;

    /**
     * 学生姓名
     */
    private String studentname;

    /**
     * 学生性别
     */
    private String studentsex;

    /**
     * 学生班级
     */
    private String studentclass;

    /**
     * 学生学院
     */
    private String studentcollege;

    /**
     * 导师工号
     */
    private String mentoraccount;

    /**
     * 导师姓名
     */
    private String mentorname;

    /**
     * 导师性别
     */
    private String mentorsex;

    /**
     * 导师学院
     */
    private String mentorcollege;

    /**
     * 轮次:1/2/3
     */
    private Integer round;

    private static final long serialVersionUID = 1L;
}
代码
    /**
     * 管理员导出匹配成功的导师和学生信息
     * @param response
     * @return
     */
    @GetMapping("/match/export")
    @ApiOperation(value = "管理员导出匹配成功的导师和学生信息")
    public void exportMatchResult(HttpServletResponse response) throws IOException {
        // 设置响应头
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 设置防止中文名乱码
        String filename = URLEncoder.encode("双选结果", "utf-8");
        // 文件下载方式(附件下载还是在当前浏览器打开)
        response.setHeader("Content-disposition", "attachment;filename=" +
                filename + ".xlsx");
        //查询所有匹配成功的导师和学生信息
        List<MatchRecordQueryVO> matchResults = matchResultService.listMatchRecordByPage(new MatchRecordQueryRequest(), 1, 1000).getRecords();
        // 构建写入到excel文件的数据
        EasyExcel.write(response.getOutputStream(), MatchRecordQueryVO.class)
                .sheet("双选结果")
                .doWrite(matchResults);
    }

标签:存储,String,EasyExcel,excel,private,导入,public
From: https://blog.csdn.net/hrh1234h/article/details/144182131

相关文章

  • 将本地的.gguf文件导入ollama
    文章目录1.创建Modelfile文件2.使用ollama进行导入2.1启动ollama服务2.2导入模型2.3运行模型1.创建Modelfile文件并写入FROM./model.gguf将./model.gguf换成自己的模型文件地址,最好是吧Modelfile文件跟model.gguf放在一起2.使用ollama进行导入2.1启动olla......
  • 在Java中使用Apache POI导入导出Excel(一)
    Excel导入导出应用场景在日常的管理系统应用场景中,进行Excel表格的导入导出是比较常见的需求,比如电商平台、企业管理系统、库存管理系统、人事管理系统等等,基本都需要使用数据进行分析,需要将已有的数据通过Excel导入到系统中,或者将系统分析的结果导出到Excel文件中,可以说在这......
  • easyexcel导出头部样式设置,多个tab导出,头部自定义RGB颜色
    alibabaeasyexcel版本3.0.5,poi版本4.1.2,导出头部样式设置,多个tab导出,头部自定义RGB颜色 效果,头部三行,三个tab  下面贴出代码:packagecom.alpha.erp.dto.accounts;importcom.alibaba.excel.metadata.Head;importcom.alibaba.excel.metadata.data.WriteCellDa......
  • 在使用 PowerShell 与 Excel COM 对象交互时,Get-Member 命令通常用于查看对象的成员(方
    在使用PowerShell与ExcelCOM对象交互时,Get-Member命令通常用于查看对象的成员(方法、属性等)。不过,Excel的COM对象可能会出现一些成员在使用Get-Member时无法完全显示的情况,尤其是在显示属性或方法时没有完全列出所有可用的成员。为了解决这个问题,可以使用以下几种方法来......
  • 使用Java导出excel内包含图片
    功能使用点最近公司需要开发一个数据表格导出excel的功能,普通的excel表格很好解决,网上有很多方法,下次写篇文章记录我的方法,但开发到有一个需求是excel是需要带图片的还是有些难度的,网上找了很多方案都无法适配,这里我记录下使用的方法。这里最后是在这篇文章上进行了优化,优化......
  • 使用phpMyAdmin导入和恢复大体积SQL文件
    修改 config.inc.php 文件找到phpMyAdmin的 config.inc.php 文件。添加或修改以下配置:$cfg['UploadDir']='ImportSQLFile';$cfg['SaveDir']='ExportSQLFile';UploadDir 用于导入文件,SaveDir 用于导出文件。创建文件夹在phpMyAdmin根目录下创建......
  • 根据链接自动生成二维码,并嵌入Excel后导出
    文章目录1.需求2.依赖3.主体方法1.需求根据每个用户链接自动生成二维码,导出用户基础信息和二维码到excel中效果如下:2.依赖<dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><versi......
  • cURL全攻略:从浏览器复制到JMeter/Postman的一键导入
    前言        在当今的数字化时代,cURL作为一款强大的命令行工具和数据传输库,已成为开发、调试和测试过程中不可或缺的利器。它支持多种协议,如HTTP、HTTPS等,能够轻松实现数据的上传与下载,发送各种HTTP请求,并灵活设置请求头和Cookies。本文旨在详细介绍cURL的基本概念、......
  • 云端地球如何进行标注导入导出?
    云端地球支持标注导入导出,与Dasviewer、CAD等软件进行数据流转。标注导入1.点击【添加标注组】,在标注组上点击【导入标注】,支持导入GeoJSON,KML,CSV格式文件。2.导入的KML在标注组里以点线面等标注的形式展示,且可进行重新编辑。标注导出1.在模型上进行点、线、面......
  • DataGrip如何导入和导出sql文件
    导出右键选择需要导出的数据库名称,我这里选择的是company然后依次按图操作即可选择好后会弹出一个窗口第一个路径选择mysql根目录下的/bin/mysqldump.exe程序,根据自身情况选择第二个路径为保存路径,我D盘下的mysql_File\DataGrip,名称默认为company.sql导出是提示......