Java利用EasyExcel实现导出导入功能的示例代码

   2023-02-09 学习力0
核心提示:目录前言一.主要实现步骤1.@ExcelProperty注解2.导入模板2.创建导入模板下载类3.创建导入监听器,监听器负责处理数据二.值得注意的地方1.下拉列表及单选框2.级联操作三.总结前言最近的项目中模块需要用到Excel的导入,在同事的建议下选择了EasyExcel。看了一下E

前言

最近的项目中模块需要用到Excel的导入,在同事的建议下选择了EasyExcel。看了一下EasyExcel的介绍,其是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。那废话不多说,直接上手试试,用代码试试EasyExcel是否真的那么好用。

一.主要实现步骤

1.@ExcelProperty注解

我们需要导入的类的字段需要用到注解@ExcelProperty("列名"),这里特别注意的是一定得跟对应的导入模板里的表头保持一致,不然导入的时候匹配不上。

//导出导入类使用注解
@ExcelProperty("表头对应的中文列名")
private String data;

2.导入模板

public void exportTemplate(HttpServletResponse response, HttpServletRequest request) throws UnsupportedEncodingException {
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    String fileName="数据模板";
    fileName = URLEncoder.encode(fileName, "UTF-8");
    fileName = new String(fileName.getBytes("utf-8"),"ISO-8859-1");
    String filePath = new ClassPathResource("docs/other/".concat(fileName).concat(dateFormat.format(new Date())).concat(".xlsx")).getPath();
    //导出模板表头
    List<String> headers = Arrays.asList("列名");
    List list = new ArrayList();
    PoiUtil.exportTemplateData(filePath,headers,list);
    //获取文件流返回给客户端
    DownloadFileUtil.downloadFile(response, request, filePath);
}
//构造模板基础数据,比如下拉列表及其校验规则
public static void exportTemplateData(String filePath, List<String> headers, List list) {
        //证件类型 下拉
        List<String> certificationTypeAttributeList = new ArrayList<String>();
        certificationTypeAttributeList.add("身份证");
        certificationTypeAttributeList.add("户口簿");
        certificationTypeAttributeList.add("护照");
        certificationTypeAttributeList.add("其他");
        // 2.创建Excel
        // 1)创建workbook
        HSSFWorkbook hssfWorkBook = new HSSFWorkbook();
        // 2)创建sheet
        HSSFSheet mainSheet = hssfWorkBook.createSheet(MAIN_SHEET);// 主sheet
        // 用于展示
        //2.1 创建表头,供用户输入
        initHeaders(hssfWorkBook, mainSheet, headers);
        //导出数据到主sheet
        setMainSheet(mainSheet, list);
        // attribute 下拉框 sheet
        HSSFSheet certificationTypeAttributeSheet= hssfWorkBook.createSheet(CERTIFICATIONTYPE_ATTRIBUTE_STATUS);
 hssfWorkBook.setSheetHidden(hssfWorkBook.getSheetIndex(certificationTypeAttributeSheet), true);// 设置sheet是否隐藏

        // 3.写入数据
    writeData(hssfWorkBook, mapSheet, mapOneList, map);
        //证件类型位
        writeDropDownData(hssfWorkBook, certificationTypeAttributeSheet, certificationTypeAttributeList, CERTIFICATIONTYPE_ATTRIBUTE_STATUS);

        // 4.设置数据有效性
        setDataValid(hssfWorkBook, mainSheet,"boundaryMarking");
        FileOutputStream os = null;
        try {
            String exisname = filePath.substring(0, filePath.lastIndexOf("/"));
            File f = new File(exisname);
            if (!f.exists()) {
                f.mkdirs();//创建目录
            }
            // 创建可写入的Excel工作簿
            File file = new File(filePath);
            if (!file.exists()) {
                boolean bool = file.createNewFile();
                System.out.println(bool);
            } else {
                file.delete();
                file.createNewFile();
            }
            os = new FileOutputStream(filePath);
            hssfWorkBook.write(os);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(os);
        }
    }

2.创建导入模板下载类

用于下载后填充数据进行导入操作

public static void downloadFile(HttpServletResponse response, HttpServletRequest request, String filePath) {
    try {
        //获取文件
        File file = new File(filePath);
        String fileName = file.getName();
        response.reset();
        ServletOutputStream out = response.getOutputStream();
        request.setCharacterEncoding("UTF-8");
        int BUFFER = 1024 * 10;
        byte data[] = new byte[BUFFER];
        BufferedInputStream bis = null;
        //获取文件输入流
        InputStream inputStream = new BufferedInputStream(new FileInputStream(filePath));
        // 以流的形式下载文件。
        DataInputStream fis = new DataInputStream(inputStream);
        int read;
        bis = new BufferedInputStream(fis, BUFFER);
        response.setContentType("application/OCTET-STREAM");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
        while ((read = bis.read(data)) != -1) {
            out.write(data, 0, read);
        }
        fis.close();
        bis.close();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        File file = new File(filePath);
        //删除临时文件
        if (file.exists()) {
            file.delete();
        }
    }
}

3.创建导入监听器,监听器负责处理数据

比如数据的校验、转换、业务逻辑处理、数据入库操作。我感觉用监听器比较麻烦直接使用了另外一种做法,对监听器感兴趣的小伙伴可以去看看

//从前端接收传过来的文件
InputStream inputStream = file.getInputStream();
List<DataModel> list = EasyExcel.read(inputStream).head(DataModel.class).sheet().doReadSync();
//对解析到数据进行逻辑操作......

二.值得注意的地方

1.下拉列表及单选框

如果需要导入的列名需要用到大量的下拉列表,单选框,在创建导入模板里就需要提前将其需要填充的数据从数据库或者接口里获取到先进行下拉列表或者单选框的数据填充。而且填充的只能是中文,这就涉及到一个问题,在进行导入处理数据时还需要将中文的转换为其对应的编码入库,这时就比较麻烦了。

2.级联操作

遇到到省市区三级联或者四级联时,同样需要提前进行数据填充,还要维护好级联关系。另外就是虽然省市区的变化不会太大,但是出于数据的严谨性需要定期同步最新的省市区数据,废弃掉在此之前的数据模板(模板导出时文件名带当前日期,用日期进行判断),如果业务不需要这么严谨这点可以不用考虑。

三.总结

按业务场景用了一下,感觉挺不错,比之前一步步的操作方便多了,导出导入都很快,而且都是流操作,不会产生额外的临时文件。不过也由于Excel本身的一些限制,在一些业务场景下使用起来就很费劲,比如有大量下拉列表的这种业务场景就不太适用。对这块感兴趣的小伙伴可以一起交流交流。

原文地址:https://juejin.cn/post/7169074263985487908
 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • #新闻拍一拍# Oracle 调研如何避免让 Java 开发者投奔 Rust 和 Kotlin | Linux 中国
    #新闻拍一拍# Oracle 调研如何避免让 Java 开发
     导读:• 英特尔对迟迟不被 Linux 主线接受的 SGX Enclave 进行了第 38 次修订 • ARM 支持开源的 Panfrost Gallium3D 驱动本文字数:977,阅读时长大约:1分钟作者:硬核老王Oracle 调研如何避免让 Java 开发者投奔 Rust 和 KotlinOracle 委托分析公司 Omd
    03-08
  • oogle的“ JavaScript杀手” Dart 与JavaScript的比较
    oogle的“ JavaScript杀手” Dart 与JavaScript
    JavaScript通常被称为浏览器脚本语言,但它也已扩展到许多服务器端和移动应用程序开发环境。JS已经存在了将近20年,可以肯定地说它确实是一种成熟且稳定的编程语言。在Facebook发布React和React Native框架之后,JS变得越来越流行。JavaScript具有自己的软件
    03-08
  • sf02_选择排序算法Java Python rust 实现
    Java 实现package common;public class SimpleArithmetic {/** * 选择排序 * 输入整形数组:a[n] 【4、5、3、7】 * 1. 取数组编号为i(i属于[0 , n-2])的数组值 a[i],即第一重循环 * 2. 假定a[i]为数组a[k](k属于[i,n-1])中的最小值a[min],即执行初始化 min =i
    02-09
  • Delphi XE6 通过JavaScript API调用百度地图
    Delphi XE6 通过JavaScript API调用百度地图
    参考昨天的内容,有朋友还是问如何调用百度地图,也是,谁让咱都在国内呢,没办法,你懂的。 首先去申请个Key,然后看一下百度JavaScript的第一个例子:http://developer.baidu.com/map/jsdemo.htm下一步,就是把例子中的代码,移动TWebBrower中。 unit Unit
    02-09
  • JavaScript面向对象轻松入门之抽象(demo by ES5
    抽象的概念  狭义的抽象,也就是代码里的抽象,就是把一些相关联的业务逻辑分离成属性和方法(行为),这些属性和方法就可以构成一个对象。  这种抽象是为了把难以理解的代码归纳成与现实世界关联的概念,比如小狗这样一个对象:属性可以归纳出“毛色”、
    02-09
  • Java与Objective-C的渊源 objective-c和c++的区
    java创始成员Patrick Naughton回忆,通常人们会认为Java是学Modula-3和C+,其实这些都是谣传,而对Java影响比较大的则是Objective-C:单 继承、动态绑定和加载、类对象、纯虚函数、反射、原始类型包装类等。Java的接口直接抄自OC的协议。  Objective-C是扩
    02-09
  • Java项目导出数据为 PDF 文件的操作代码
    Java项目导出数据为 PDF 文件的操作代码
    目录Java项目如何导出数据为 PDF 文件?一、代码结构如下二、代码说明1、添加依赖 pom.xml2、HTML模板文件 audit_order_record.html3、添加字体4、PDF 导出工具类5、导出接口6、打开浏览器测试三、效果图Java项目如何导出数据为 PDF 文件?一个小需求,需要将
  • 盘点Java中延时任务的多种实现方式 java 延时队列怎么实现
    盘点Java中延时任务的多种实现方式 java 延时队
    目录场景描述实现方式一、挂起线程二、ScheduledExecutorService 延迟任务线程池三、DelayQueue(延时队列)四、Redis-为key指定超时时长,并监听失效key五、时间轮六、消息队列-延迟队列场景描述①需要实现一个定时发布系统通告的功能,如何实现? ②支付超时
  • Java Semaphore信号量使用分析讲解
    Java Semaphore信号量使用分析讲解
    目录前言介绍和使用API介绍基本使用原理介绍获取许可acquire()释放许可release()总结前言大家应该都用过synchronized 关键字加锁,用来保证某个时刻只允许一个线程运行。那么如果控制某个时刻允许指定数量的线程执行,有什么好的办法呢? 答案就是JUC提供的信
  • 【Java并发入门】03 互斥锁(上):解决原子性问题
    【Java并发入门】03 互斥锁(上):解决原子性
    原子性问题的源头是线程切换Q:如果禁用 CPU 线程切换是不是就解决这个问题了?A:单核 CPU 可行,但到了多核 CPU 的时候,有可能是不同的核在处理同一个变量,即便不切换线程,也有问题。所以,解决原子性的关键是「同一时刻只有一个线程处理该变量,也被称
    02-09
点击排行