栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot整合Easyexcel操作Excel,闲暇之余,让我们学习更多

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot整合Easyexcel操作Excel,闲暇之余,让我们学习更多

easyexcel

3.0.2

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter

org.projectlombok

lombok

com.alibaba

fastjson

1.2.74

org.springframework.boot

spring-boot-starter-test

junit

junit

4.12

1.2、项目结构

搭建个项目大家都会啦,这里放一下我自己的结构。

二、读Excel操作 readExcel


2.1、前期准备

准备好一个xslx文件模板,我就是准备了我自己了。

我们创建一个实体类,来对应xlsx中的列名。

实体类

@Data

public class DemoModel {

@ExcelProperty(value = “博客名”, index = 0)

private String name;

@ExcelProperty(value = “社区”, index = 1)

private String communityName;

@ExcelProperty(value = “主页”, index = 2)

private String homePageUrl;

@ExcelProperty(value = “涉及领域”, index = 3)

private String specialty;

@ExcelProperty(value = “联系邮箱”, index = 4)

private String email;

@DateTimeFormat(“yyyy-MM-dd HH:mm:ss”)

@ExcelProperty(value = “发布的第一篇原创文章”, index = 5)

private String startDate;

}

监听器

public class DemoListener extends AnalysisEventListener {

private static final Logger LOGGER = LoggerFactory.getLogger(DemoListener.class);

private static final int BATCH_COUNT = 10;

List list = new ArrayList();

private DemoMapper demoMapper;

public DemoListener() {

// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数

demoMapper = new DemoMapper();

}

public DemoListener(DemoMapper demoMapper) {

this.demoMapper = demoMapper;

}

@Override

public void invoke(DemoModel data, AnalysisContext context) {

LOGGER.info(“解析到一条数据:{}”, JSON.toJSonString(data));

list.add(data);

// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM

if (list.size() >= BATCH_COUNT) {

saveData();

// 存储完成清理 list

list.clear();

}

}

@Override

public void doAfterAllAnalysed(AnalysisContext context) {

// 这里也要保存数据,确保最后遗留的数据也存储到数据库

saveData();

LOGGER.info(“所有数据解析完成!”+count);

}

private void saveData() {

LOGGER.info("{}条数据,开始存储数据库!", list.size());

//进行数据库层面操作

demoMapper.save(list);

LOGGER.info(“存储数据库成功!”);

}

}

mapper层:此处只是模拟

@Repository

public class DemoMapper {

public void save(List demoModels){

System.out.println(“Mapper:”+demoModels);

}

}

类型转换

2.2、读单个Sheet

@Test

public void demo1TestRead() {

// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去

// 写法1:

String fileName = “E:project_codecommons-utilsspringboot-excelsrcmainresourcesexceldemo.xlsx”;

// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭

EasyExcel.read(fileName, DemoModel.class, new DemoListener()).sheet().doRead();

}

这里我们无需指定sheet,因为我们就一个工作表,直接默认就完事了。

控制台输出:

23:35:52.583 [main] INFO com.crush.excel.listener.DemoListener - 解析到一条数据:{“communityName”:“掘金”,“email”:“nzc_wyh@163.com”,“homePageUrl”:“https://juejin.cn/user/2859142558267559”,“name”:“宁在春”,“specialty”:“Java后端开发”,“startDate”:“2021-10-31 12:01:52”}

23:35:52.584 [main] INFO com.crush.excel.listener.DemoListener - 解析到一条数据:{“communityName”:“CSDN”,“email”:“nzc_wyh@163.com”,“homePageUrl”:“https://blog.csdn.net/weixin_45821811?spm=1000.2115.3001.5343”,“name”:“宁在春”,“specialty”:“Java后端开发”,“startDate”:“2020-05-11 12:01:52”}

23:35:52.585 [main] INFO com.crush.excel.listener.DemoListener - 2条数据,开始存储数据库!

Mapper:[DemoModel(name=宁在春, communityName=掘金, homePageUrl=https://juejin.cn/user/2859142558267559, specialty=Java后端开发, email=nzc_wyh@163.com, startDate=2021-10-31 12:01:52), DemoModel(name=宁在春, communityName=CSDN, homePageUrl=https://blog.csdn.net/weixin_45821811?spm=1000.2115.3001.5343, specialty=Java后端开发, email=nzc_wyh@163.com, startDate=2020-05-11 12:01:52)]

23:35:52.617 [main] INFO com.crush.excel.listener.DemoListener - 存储数据库成功!

23:35:52.618 [main] INFO com.crush.excel.listener.DemoListener - 所有数据解析完成!2

这是最简单的方式,也是读取Excel中,单个Sheet的操作,但我们平时中,一个excel是会有多个工作表的。

如下:

2.3、读多个Sheet

其实本质上还是操作单个sheet工作表。

因为各个Sheet的数据不同,因而要建立多个Model和多个监听类。

这边就不再把全部model贴出了,如果不太明白,可以去文末看看源码。

同时也要创建多个监听器。

mapper层在这里就省略了哈。

@Test

public void repeatedRead() {

String fileName = “E:project_codecommons-utilsspringboot-excelsrcmainresourcesexceldocument_Success.xlsx”;

// 读取需要读取的Sheet

ExcelReader excelReader = EasyExcel.read(fileName).build();

// 自己使用功能必须不同的Listener

ReadSheet readSheet1 =

EasyExcel.readSheet(0).head(documentModel.class).registerReadListener(new documentListener()).build();

ReadSheet readSheet2 =

EasyExcel.readSheet(1).head(TemplateModel.class).registerReadListener(new TemplateListener()).build();

ReadSheet readSheet3 =

EasyExcel.readSheet(2).head(SectionModel.class).registerReadListener(new SectionListener()).build();

ReadSheet readSheet4 =

EasyExcel.readSheet(3).head(QuestionModel.class).registerReadListener(new QuestionListener()).build();

ReadSheet readSheet5 =

EasyExcel.readSheet(4).head(OptionModel.class).registerReadListener(new OptionListener()).build();

ReadSheet readSheet6 =

EasyExcel.readSheet(5).head(ConditionModel.class).registerReadListener(new ConditionListener()).build();

ReadSheet readSheet7 =

EasyExcel.readSheet(6).head(QuestionTooltipModel.class).registerReadListener(new QuestionTooltipListener()).build();

ReadSheet readSheet8 =

EasyExcel.readSheet(7).head(OptionTooltipModel.class).registerReadListener(new OptionTooltipListener()).build();

// 这里注意 一定要把sheet1 sheet2 一起传进去,不然有个问题就是03版的excel 会读取多次,浪费性能

excelReader.read(readSheet1, readSheet2, readSheet3, readSheet4, readSheet5, readSheet6, readSheet7, readSheet8);

// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的

excelReader.finish();

}

控制台输出:

23:42:19.733 [main] INFO com.crush.excel.listener.documentListener - 解析到一条数据:{“customerId”:1,“name”:“document i”}

23:42:19.755 [main] INFO com.crush.excel.listener.TemplateListener - 解析到一条数据:{“documentType”:1,“fontStyleId”:1,“lobId”:1,“name”:“Template q”,“userGroupId”:1}

23:42:19.785 [main] INFO com.crush.excel.listener.SectionListener - 解析到一条数据:{“index”:1,“name”:“Section 1”,“order”:1}

23:42:19.785 [main] INFO com.crush.excel.listener.SectionListener - 解析到一条数据:{“index”:2,“name”:“Section 2”,“order”:2}

23:42:19.823 [main] INFO com.crush.excel.listener.QuestionListener - 解析到一条数据:{“allowComments”:“false”,“answerType”:“1”,“enhancedField”:“false”,“index”:“1”,“order”:“1”,“question”:“This is Simple Question”,“required”:“true”,“sectionIndex”:“1”}

23:42:19.824 [main] INFO com.crush.excel.listener.QuestionListener - 解析到一条数据:{“allowComments”:“false”,“answerType”:“2”,“enhancedField”:“false”,“index”:“2”,“order”:“2”,“question”:“This is Simple Question”,“required”:“false”,“sectionIndex”:“1”}

23:42:19.825 [main] INFO com.crush.excel.listener.QuestionListener - 解析到一条数据:{“allowComments”:“false”,“answerType”:“10”,“enhancedField”:“false”,“index”:“3”,“order”:“3”,“question”:“This is Simple Question”,“required”:“false”,“sectionIndex”:“1”}

23:42:19.826 [main] INFO com.crush.excel.listener.QuestionListener - 解析到一条数据:{“allowComments”:“false”,“answerType”:“3”,“enhancedField”:“false”,“index”:“4”,“order”:“1”,“question”:“This is Simple Question”,“required”:“true”,“sectionIndex”:“2”}

23:42:19.827 [main] INFO com.crush.excel.listener.QuestionListener - 解析到一条数据:{“allowComments”:“false”,“answerType”:“5”,“enhancedField”:“false”,“index”:“5”,“order”:“2”,“question”:“This is Simple Question”,“required”:“false”,“sectionIndex”:“2”}

23:42:19.831 [main] INFO com.crush.excel.listener.QuestionListener - 解析到一条数据:{“allowComments”:“false”,“answerType”:“12”,“enhancedField”:“false”,“index”:“6”,“order”:“3”,“question”:“This is Simple Question”,“required”:“true”,“sectionIndex”:“2”}

23:42:19.847 [main] INFO com.crush.excel.listener.OptionListener - 解析到一条数据:{“index”:1,“order”:1,“questionIndex”:3,“value”:“Option 1”}

23:42:19.848 [main] INFO com.crush.excel.listener.OptionListener - 解析到一条数据:{“index”:2,“order”:2,“questionIndex”:3,“value”:“Option 2”}

23:42:19.849 [main] INFO com.crush.excel.listener.OptionListener - 解析到一条数据:{“index”:3,“order”:3,“questionIndex”:3,“value”:“Option 3”}

23:42:19.849 [main] INFO com.crush.excel.listener.OptionListener - 解析到一条数据:{“index”:4,“order”:4,“questionIndex”:3,“value”:“Option 4”}

23:42:19.850 [main] INFO com.crush.excel.listener.OptionListener - 解析到一条数据:{“index”:5,“order”:1,“questionIndex”:6,“value”:“Option 1”}

23:42:19.850 [main] INFO com.crush.excel.listener.OptionListener - 解析到一条数据:{“index”:6,“order”:2,“questionIndex”:6,“value”:“Option 2”}

23:42:19.851 [main] INFO com.crush.excel.listener.OptionListener - 解析到一条数据:{“index”:7,“order”:3,“questionIndex”:6,“value”:“Option 3”}

23:42:19.868 [main] INFO com.crush.excel.listener.ConditionListener - 解析到一条数据:{“action”:1,“index”:1,“questionIndex”:1,“selectedAnswer”:“Test”,“triggerQuestionIndex”:1,“triggerSectionIndex”:1}

23:42:19.869 [main] INFO com.crush.excel.listener.ConditionListener - 解析到一条数据:{“action”:1,“index”:2,“questionIndex”:2,“selectedAnswer”:“Test”,“triggerSectionIndex”:2}

23:42:19.888 [main] INFO com.crush.excel.listener.QuestionTooltipListener - 解析到一条数据:{“endIndex”:10,“index”:1,“parentIndex”:1,“startIndex”:1,“text”:“Sample Tooltip”}

23:42:19.908 [main] INFO com.crush.excel.listener.OptionTooltipListener - 解析到一条数据:{“endIndex”:10,“index”:1,“parentIndex”:1,“startIndex”:1,“text”:“Sample Tooltip”}

23:42:19.910 [main] INFO com.crush.excel.listener.OptionTooltipListener - 解析到一条数据:{“endIndex”:10,“index”:2,“parentIndex”:2,“startIndex”:1,“text”:“Sample Tooltip”}

我们可以在获取到数据的时候,存储进数据库。另外我们常常会上传excel,进行数据的导入,所以我们再来看看web中的excel的读。

2.4、web中的读

@AutowiredDemoMapper demoMapper;@PostMapping(“upload”)@ResponseBodypublic String upload(MultipartFile file) throws IOException { EasyExcel.read(file.getInputStream(), DemoModel.class, new DemoListener(demoMapper)).sheet().doRead(); return “success”;}

我想这样的场景是我们在Web开发中最常用到的那种。

如果是内存足够,数据量不是特别大的话,像我这么写也是完全能够接受的。

如果是操作数据十万或几十万数据的大兄弟,可以前去官网看看优化方案。Easyexcel | github

三、写Excle操作 writeExcel


3.1、写到单个Sheet中

@Test

public void simpleWrite() {

DemoModel model = new DemoModel();

model.setName(“宁在春”);

model.setCommunityName(“知乎”);

model.setHomePageUrl(“https://www.zhihu.com/creator/manage/creation/all”);

model.setEmail(“nza_wyh@163.com”);

model.setSpecialty(“SpringBoot”);

model.setStartDate(“2021-10-31 12:00:00”);

DemoModel model2 = new DemoModel();

model2.setName(“宁在春2”);

model2.setCommunityName(“知乎2”);

model2.setHomePageUrl(“2https://www.zhihu.com/creator/manage/creation/all”);

model2.setEmail(“nza_wyh@163.com2”);

model2.setSpecialty(“SpringBoot2”);

model2.setStartDate(“2021-10-31 12:00:00”);

List models = new ArrayList();

models.add(model);

models.add(model2);

// 写法1

String fileName = “E:project_codecommons-utilsspringboot-excelsrcmainresourcesexceldemo2.xlsx”;

// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭

// 如果这里想使用03 则 传入excelType参数即可

EasyExcel.write(fileName, DemoModel.class).sheet(0).doWrite(models);

// // 写法2

// // 这里 需要指定写用哪个class去写

ExcelWriter excelWriter = EasyExcel.write(fileName, DemoModel.class).build();

WriteSheet writeSheet = EasyExcel.writerSheet(0).build();

excelWriter.write(models, writeSheet);

// 千万别忘记finish 会帮忙关闭流

excelWriter.finish();

}

这是操作excel文件中单个Sheet的操作,十分简单。

EasyExcel.write(fileName, DemoModel.class).sheet(0).doWrite(models);关于sheet()中的参数0,我们其实就一张Sheet工作表,填与不填其实都一样,另外,此处也可以填sheet表名字,也是一样 。

操作结果:

注意:

注意:我发现如果我是直接向这个excel文件进行写入,默认是采用覆盖的方式进行写入,即之前有的信息都会被覆盖掉。

测试:

写之前:

写之后:

补充:

如果我们直接写,是采用覆盖模式的,这肯定是不符合一些业务场景的。所以肯定有解决方式的,

easyexcel中对此也是有处理的。

它有一个根据模板写入,模板如下:

@Test

public void templateWrite() {

DemoModel model = new DemoModel();

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/673207.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号