赞
踩
easyExcel是阿里巴巴开源poi插件之一,当前最新版本2.1.3,poi版本3.17
主要解决了poi框架使用复杂,sax解析模式不容易操作,数据量大起来容易OOM,解决了POI并发造成的报错
注解式自定义操作。
输入输出简单,提供输入输出过程的接口
支持一定程度的单元格合并等灵活化操作
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>easyexcel</artifactId>
- <version>2.1.3</version>
- </dependency>
实体类对需要导出或者导入的字段增加@ExcelProperty注解,index值为对应excel中的列,value为表头,format为日期格式化
- public class PersonDto{
- /** id */
- @ExcelProperty(index = 0 , value = "id")
- private String id;
- /** 姓名 **/
- @ExcelProperty(index = 1 , value = "姓名")
- private String name;
- /** 生日 **/
- @ExcelProperty(index = 2 , value = "生日" , format = "yyyy-MM-dd")
- //新版本提供了一个@com.alibaba.excel.annotation.format.DateTimeFormatDateTimeFormat替代format属性
- private String birth;
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getBirth() {
- return birth;
- }
-
- public void setBirth(String birth) {
- this.birth = birth;
- }
- }
- public class TestExcel {
-
- private List<PersonDto> createModelList() {
- List<PersonDto> PersonDtos = new ArrayList<>();
-
- for (int i = 0; i < 100; i++) {
- PersonDto personDto = new PersonDto();
- personDto.setName("学Java"+i);
- personDto.setId(""+i);
- personDto.setBirth(new Date().toString());
- PersonDtos.add(personDto);
- }
-
- return PersonDtos;
- }
- /**
- * 最简单的写
- * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
- * <p>2. 直接写即可
- */
- @Test
- public void simpleWrite() {
- // 写法1
- String fileName = "D:\\person.xlsx";
- // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
- // 如果这里想使用03 则 传入excelType参数即可
- EasyExcel.write(fileName, PersonDto.class).sheet("模板").doWrite(createModelList());
-
- // 写法2
- fileName = "D:\\person.xlsx";
- // 这里 需要指定写用哪个class去写
- ExcelWriter excelWriter = EasyExcel.write(fileName, PersonDto.class).build();
- WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
- excelWriter.write(createModelList(), writeSheet);
- /// 千万别忘记finish 会帮忙关闭流
- excelWriter.finish();
- }
- }
- AnalysisEventListener<PersonDto>:
- 读取excel必须提供一个监听类继承该抽象类
-
- public void invoke(PersonDto data, AnalysisContext context)
- 在读取excel的每一行,都会去调用该监听器的invoke方法,自动传入解析好的java对象
-
- public void doAfterAllAnalysed(AnalysisContext context)
- 在读取excel结束的时候,会调用该方法
3.4.1 PersonDtoListener
-
- import com.alibaba.excel.context.AnalysisContext;
- import com.alibaba.excel.event.AnalysisEventListener;
-
- import java.util.ArrayList;
- import java.util.List;
-
- public class PersonDtoListener extends AnalysisEventListener<PersonDto> {
- /**
- * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
- */
- private static final int BATCH_COUNT = 5;
- List<PersonDto> list = new ArrayList<PersonDto>();
- /**
- * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
- */
- private PersonDao personDao;
-
- public PersonDtoListener() {
-
- }
-
- /**
- * 官方问题提到不能用spring管理该监听器对象,所以不能直接用依赖注入注解注入
- * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
- *
- * @param personDAO
- */
- public PersonDtoListener(PersonDao personDAO) {
- this.personDao = personDAO;
- }
-
- /**
- * 这个每一条数据解析都会来调用
- *
- * @param data
- * one row value. Is is same as {@link AnalysisContext#readRowHolder()}
- * @param context
- */
- public void invoke(PersonDto data, AnalysisContext context) {
-
- list.add(data);
- // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
- if (list.size() >= BATCH_COUNT) {
- saveData();
- // 存储完成清理 list
- list.clear();
- }
- }
-
- /**
- * 所有数据解析完成了 都会来调用
- *
- * @param context
- */
- public void doAfterAllAnalysed(AnalysisContext context) {
- // 这里也要保存数据,确保最后遗留的数据也存储到数据库
- saveData();
-
- }
-
- /**
- * 加上存储数据库
- */
- private void saveData() {
- System.out.println(list);
- personDao.save(list);
-
- }
- }
3.4.2 测试类
- /**
- * 最简单的读
- * <p>1. 创建excel对应的实体对象 参照{@link cn.nyse.entity.PersonDto}
- * <p>2. 由于默认异步读取excel,所以需要创建excel一行一行的回调监听器,参照{@link cn.nyse.entity.PersonDtoListener}
- * <p>3. 直接读即可
- */
- @Test
- public void simpleRead() {
- // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
- // 写法1:
- String fileName = "F:\\dfbz\\课件2.0\\guguanjia2.0\\some.xlsx";
- // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
- EasyExcel.read(fileName, PersonDto.class, new PersonDtoListener()).sheet().doRead();
-
- // 写法2:
- fileName = "F:\\dfbz\\课件2.0\\guguanjia2.0\\some.xlsx";
- ExcelReader excelReader = EasyExcel.read(fileName, PersonDto.class, new PersonDtoListener()).build();
- ReadSheet readSheet = EasyExcel.readSheet(0).build();
- excelReader.read(readSheet);
- // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
- excelReader.finish();
- }
1.步骤
a.在input组件中添加点击事件@click="upload"
b.在事件处理函数中传入事件对象,通过事件对象获取文件对象e.target.files[0]
c.创建表单对象let formData = new FormData();
d.放入文件对象 formData.append("file",e.target.files[0]);
d.通过axios设置请求头headers:{'content-type':'multipart/form-data'}和提交方式post
e.后台通过上传对象MultipartFile file接受
页面:
- <div id="div1">
- <input type="file" accept=".xls,.xsls" @change="upload"/>
- </div>
- <script>
- var vm = new Vue({
- el:'#app',
- /*
- 由于vue的响应式原理 data 如果是一个对象,对象中使用this不会自动绑定为vue对象,需要通过回调函数方式,vue才会在调用该函数的时候,进行双向绑定,并且自动传入
- 当前vue对象到函数中
- */
- data:function(){
- console.log(this);
- return {
- file:''
- }
-
- },
- methods:{
- upload:function(e){
- this.file = e.target.files[0];
- console.log(this.file);
- let formData = new FormData();
- formData.append("file",this.file);
- axios({
- method:'post',
- headers:{'content-type':'multipart/form-data'},
- url:'/guguanjia/manager/area/importExcel',
- data:formData
- }).then(response =>{
- console.log(response.data);
- }).catche(function(error){
-
- });
-
- }
- }
-
- });
-
- </script>
后台
- @RequestMapping("importExcel")
- public void importExcel(@RequestParam("file")MultipartFile file){
- System.out.println((file.getOriginalFilename()));
- 。。。
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。