一、Springboot + Easyexcel读取写入数据,多头行数,多sheet,复杂表头简单实现
1. 导入依赖,阿里的easyexcel插件
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.6</version>
</dependency
创建一个用来 读取 excel的实体类
实体类的属性可以用
-
@ExcelProperty(index = 0),index=0,找的是上图 A列(第一列)
-
@ExcelProperty(value = “标号”)
两种都可以用,但是不要两个一起用
实体类:
实体类中可以使用@DateFormat(阿里包下的)注解:
要使用String类型来接收数据才有用
@Data
public class TemplateEntity {@ExcelProperty("标号")private Integer label;@ExcelProperty("字符串")private String str;@ExcelProperty("数字")private Integer num;@ExcelProperty("时间")// 这里需要用string接收才会格式化@DateTimeFormat("yyyy-MM-dd")private String date;}
————————————————
定义一个 监听类:
public class TemplateListener extends AnalysisEventListener<TemplateEntity> {private List<TemplateEntity> list = new ArrayList<>();// 一条一条读取数据,全部添加到list集合里@Overridepublic void invoke(TemplateEntity data, AnalysisContext analysisContext) {list.add(data);}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}public List<TemplateEntity> getData() {return list;}
}
service:
public interface TemplateService {/*** 导入excel*/Result importExcel(MultipartFile file) throws IOException;
}@Service
public class TemplateServiceImpl implements TemplateService {@Overridepublic Result importExcel(MultipartFile file) throws IOException{List<TemplateEntity> entities = getTemplateEntities(file);// 处理数据System.out.println(entities);return Result.success(entities);}// 读取 excel 数据private List<TemplateEntity> getTemplateEntities(MultipartFile file) throws IOException {TemplateListener listener = new TemplateListener(); // 定义的 listenerEasyExcel.read(file.getInputStream(), TemplateEntity.class, listener).sheet().doRead();// 返回 所有数据return listener.getData();}
}
Controller 上传文件接口
@RestController
@RequestMapping("/sys")
public class TemplateController {@Autowiredprivate TemplateService templateService;@RequestMapping("/import")public Result importData(@RequestPart("file") MultipartFile file) throws IOException{return templateService.importExcel(file);}
}
Postman测试
{"code": 200,"msg": "处理成功","data": [{"label": 1,"str": "a","num": 20},{"label": 2,"str": "b","num": 30},{"label": 3,"str": "c","num": 40},...
}
————————————————
多sheet
两sheet表头数据不一致
这里为了演示效果,sheet1和sheet3是不同表头的,sheet2目前是空的数据表
思路:需要定义各自的excel接收数据的实体类,然后创建各自的监听类,重写方法
读取时,指定不同的监听类,excel接收数据的实体类对象,然后放入map中返回即可
具体实现
实体类
TemplateEntity接收sheet1
@Data
public class TemplateEntity {@ExcelProperty("标号")private Integer label;@ExcelProperty("字符串")private String str;@ExcelProperty("数字")private Integer num;@ExcelProperty(value = "时间")@DateTimeFormat("yyyy-MM-dd")private String date;
}
OtherTemplateEntity接收sheet3
@Data
public class OtherTemplateEntity {@ExcelProperty("标号")private String label;@ExcelProperty("名称")private String name;@ExcelProperty("类型")private String type;@ExcelProperty(value = "时间")@DateTimeFormat("yyyy-MM-dd")private String date;
}
监听类
同上,只是写两个各自的
controller层
@PostMapping("/importMany")
public R importMany(@RequestPart("file") MultipartFile file) throws IOException {return easyExcelService.importManyExcel(file);
}
service实现层
public R importManyExcel(MultipartFile file) throws IOException {Map<String, Object> map = getTemplateEntitiesMany(file);List<TemplateEntity> data1 = (List<TemplateEntity>) map.get("data1");List<OtherTemplateEntity> data2 = (List<OtherTemplateEntity>) map.get("data2");log.info("data1数据=={}", data1);log.info("data2数据=={}", data2);return R.success(map);
}private Map<String, Object> getTemplateEntitiesMany(MultipartFile file) throws IOException {Map<String,Object> map = new HashMap<>();TemplateListener listener = new TemplateListener(); // 定义的 listenerOtherTemplateListener otherListener = new OtherTemplateListener();ExcelReader excelReader = EasyExcel.read(file.getInputStream()).build();// 这里为了简单 所以注册了 同样的head 和Listener 自己使用功能必须不同的Listener// readSheet参数设置读取sheet的序号// 读取sheet1ReadSheet readSheet1 =EasyExcel.readSheet(0).head(TemplateEntity.class).registerReadListener(listener).build();// 读取sheet3ReadSheet readSheet2 =EasyExcel.readSheet(2).head(OtherTemplateEntity.class).registerReadListener(otherListener).build();excelReader.read(readSheet1, readSheet2);// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的excelReader.finish();// 取出数据放入map中,然后返回List<TemplateEntity> data1 = listener.getData();List<OtherTemplateEntity> data2 = otherListener.getData();map.put("data1", data1);map.put("data2", data2);return map;}
{"code": 200,"msg": "OK","message": null,"data": {"data2": [{"label": "a","name": "a1","type": "t1","date": "2022-01-07"},{"label": "b","name": "b1","type": "t2","date": "2022-01-07"}......],"data1": [{"label": 1,"str": "a","num": 20,"date": "2021-12-20"},{"label": 2,"str": "b","num": 30,"date": "2021-12-20"}......]}
}
多行头
读取时设置头行数即可
headRowNumber是头行数,如下是设置头行数2,那么读取时会从第三行开始读取数据
private List<TemplateEntity> getTemplateEntities(MultipartFile file) throws IOException {TemplateListener listener = new TemplateListener(); // 定义的 listenerEasyExcel.read(file.getInputStream(), TemplateEntity.class, listener).sheet(0).headRowNumber(2).doRead();// 返回 所有数据return listener.getData();}
读取表头数据
在监听类中重写invokeHeadMap方法,将表头数据也添加即可
public class TemplateListener extends AnalysisEventListener<TemplateEntity> {private List<TemplateEntity> list = new ArrayList<>();@Overridepublic void invoke(TemplateEntity data, AnalysisContext context) {list.add(data);}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {}public List<TemplateEntity> getData() {return list;}@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {// 读取到头数据LOGGER.info("解析到一条头数据:{}", JSON.toJSONString(headMap))}
————————————————
Springboot + Easyexcel 导出数据
简单导出excel
实体类省略,还是上面的TemplateEntity
导出excel数据,这里有两种写法,拟定好文件名称直接传入方法,会自动创建一个文件
模拟数据 10条数据
// 模拟数据
private List<TemplateEntity> exportData() {List<TemplateEntity> entities = new ArrayList<>();for (int i = 0; i< 10; i++) {TemplateEntity entity = new TemplateEntity();entity.setStr("字符串" + i);entity.setDate("数据" + i);entity.setLabel(i+1);entity.setNum(i);entities.add(entity);}return entities;
}
导出程序
public R export() {String path = "C:\\Users\\EDZ\\Desktop\\";// 写法1String fileName = path + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭// 如果这里想使用03 则 传入excelType参数即可EasyExcel.write(fileName, TemplateEntity.class).sheet("模板").doWrite(exportData());// 写法2// 这里 需要指定写用哪个class去写ExcelWriter excelWriter = EasyExcel.write(fileName, TemplateEntity.class).build();WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();excelWriter.write(exportData(), writeSheet);// 千万别忘记finish 会帮忙关闭流excelWriter.finish();return R.success();
}
————————————————
过滤导出列
public R export() {String path = "C:\\Users\\EDZ\\Desktop\\";String fileName = path + System.currentTimeMillis() + ".xlsx";// 加入要忽略date字段Set<String> excludeColumnFiledNames = new HashSet<String>();excludeColumnFiledNames.add("date");EasyExcel.write(fileName,TemplateEntity.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板").doWrite(exportData()); }
复杂头写入 合并表头
实体类
@Data
public class TemplateEntity {@ExcelProperty({"主标题", "标号"})private Integer label;@ExcelProperty({"主标题", "字符串"})private String str;@ExcelProperty({"主标题", "数字"})private Integer num;@ExcelProperty({"主标题", "时间"})@DateTimeFormat("yyyy-MM-dd")private String date;
}