1.EasyExcel簡介
EasyExcel是一個基於Java的簡單、省內存的讀寫Excel的開源項目。在盡可能節約內存的情況下支持讀寫百M的Excel。Java解析、生成Excel比較有名的框架有Apache poi、jxl。但他們都存在一個嚴重的問題就是非常的耗內存,poi有一套SAX模式的API可以一定程度的解決一些內存溢出的問題,但POI還是有一些缺陷,比如07版Excel解壓縮以及解壓后存儲都是在內存中完成的,內存消耗依然很大。easyexcel重寫了poi對07版Excel的解析,能夠原本一個3M的excel用POI sax依然需要100M左右內存降低到幾M,並且再大的excel不會出現內存溢出,03版依賴POI的sax模式。在上層做了模型轉換的封裝,讓使用者更加簡單方便。
2.Java實現EasyExcel操作
2.1 導入依賴
<dependencies> <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.1</version> </dependency> </dependencies>
2.2 寫操作
不存在Excel文件也沒關系,EasyExcel會幫我們自動創建
@Test public void test1(){ List<TestDataEntity> list=new ArrayList<>(); for (int i=0;i<=10;i++){ TestDataEntity entity=new TestDataEntity(); entity.setId(i); entity.setName("lucy"+i); entity.setAge(30+i); list.add(entity); } String fileName="D:\\upload\\01.xlsx"; EasyExcel.write(fileName,TestDataEntity.class).sheet("姓名管理").doWrite(list); }
2.3 讀操作
在實體類加上ExcelProperty注解,用於從Excel中讀取的數據進行封裝
@Data @ToString public class TestDataEntity { @ExcelProperty(value = "id",index = 0) private int id; @ExcelProperty(value = "name",index = 1) private String name; @ExcelProperty(value = "age",index = 2) private Integer age; }
編寫監聽器進行讀取操作
package com.gh.test; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import java.util.Map; /** * @Author Eric * @Date 2021/6/6 12:48 * @Version 1.0 */ public class ExcelListener extends AnalysisEventListener<TestDataEntity> { //一行一行讀取Excel數據,從第二行開始讀 @Override public void invoke(TestDataEntity testDataEntity, AnalysisContext analysisContext) { System.out.println(testDataEntity); } //讀取表頭信息 @Override public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { System.out.println("==============="); System.out.println(headMap); } //讀取之后執行 @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } }
編寫測試方法進行讀操作
@Test public void test2(){ String fileName="D:\\upload\\01.xlsx"; EasyExcel.read(fileName,TestDataEntity.class,new ExcelListener()).sheet().doRead(); }
3.EasyExcel整合springboot
3.1 導出到Excel
controller層
/** * 導出數據字典到Excel */ @GetMapping("exportDictToExcel") public Result exportDictToExcel(HttpServletResponse response){ dictService.exportDictToExcel(response); return Result.ok(); }
service層
/** * 導出數據字典 * @param response */ @Override public void exportDictToExcel(HttpServletResponse response) { //設置下載信息 response.setContentType("application/vnd.ms-excel");//application/vnd.ms-excel response.setCharacterEncoding("utf-8"); String filename="dict"; response.setHeader("Content-disposition", "attachment;filename="+ filename + ".xlsx"); //查詢數據 List<Dict> dictList = baseMapper.selectList(null); List<DictEeVo> list=new ArrayList<>(); for (Dict dict : dictList) { DictEeVo dictEeVo=new DictEeVo(); BeanUtils.copyProperties(dict,dictEeVo); list.add(dictEeVo); } try { EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet().doWrite(list); } catch (IOException e) { e.printStackTrace(); } }
前端JavaScript:
exportData() { window.location.href = 'http://localhost:8202/admin/cmn/dict/exportDictToExcel' },
3.2 從Excel導入
controller層:
/** * 從Excel導入數據到數據庫 */ @PostMapping("importDictToDatabase") public Result importDictToDatabase(MultipartFile file){ dictService.importDictToDatabase(file); return Result.ok(); }
service層:
@Override public void importDictToDatabase(MultipartFile file) { try { EasyExcel.read(file.getInputStream(),DictEeVo.class,new DictListener(baseMapper)).sheet().doRead(); } catch (IOException e) { e.printStackTrace(); } }
監聽器listener:
package com.gh.listener; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.gh.mapper.DictMapper; import com.gh.model.cmn.Dict; import com.gh.vo.cmn.DictEeVo; import org.springframework.beans.BeanUtils; public class DictListener extends AnalysisEventListener<DictEeVo> { private DictMapper dictMapper; public DictListener(DictMapper dictMapper) { this.dictMapper = dictMapper; } //一行一行讀取 @Override public void invoke(DictEeVo dictEeVo, AnalysisContext analysisContext) { //調用方法添加數據庫 Dict dict = new Dict(); BeanUtils.copyProperties(dictEeVo,dict); dictMapper.insert(dict); } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } }
表頭實體類:
@Data public class DictEeVo { @ExcelProperty(value = "id" ,index = 0) private Long id; @ExcelProperty(value = "上級id" ,index = 1) private Long parentId; @ExcelProperty(value = "名稱" ,index = 2) private String name; @ExcelProperty(value = "值" ,index = 3) private String value; @ExcelProperty(value = "編碼" ,index = 4) private String dictCode; }