官網(wǎng)解釋:
Java解析虐呻、生成Excel比較有名的框架有Apache poi掸掏、jxl船殉。但他們都存在一個(gè)嚴(yán)重的問題就是非常的耗內(nèi)存更振,poi有一套SAX模式的API可以一定程度的解決一些內(nèi)存溢出的問題,但POI還是有一些缺陷喂走,比如07版Excel解壓縮以及解壓后存儲(chǔ)都是在內(nèi)存中完成的殃饿,內(nèi)存消耗依然很大。easyexcel重寫了poi對(duì)07版Excel的解析芋肠,能夠原本一個(gè)3M的excel用POI sax依然需要100M左右內(nèi)存降低到KB級(jí)別乎芳,并且再大的excel不會(huì)出現(xiàn)內(nèi)存溢出,03版依賴POI的sax模式帖池。在上層做了模型轉(zhuǎn)換的封裝奈惑,讓使用者更加簡(jiǎn)單方便
簡(jiǎn)單來說就是對(duì)excel的讀寫操作
演示過程
1.導(dǎo)入maven依賴
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
2.實(shí)現(xiàn)簡(jiǎn)單的讀寫操作
寫入操作:
@Data
public class DemoData {
//設(shè)置excel表頭名稱
@ExcelProperty(value = "學(xué)生編號(hào)",index = 0)
private Integer sno;
@ExcelProperty(value = "學(xué)生姓名",index = 1)
private String sname;
}
public static void main(String[] args) {
//實(shí)現(xiàn)excel寫的操作
//1 設(shè)置寫入文件夾地址和excel文件名稱
String filename = "E:\\write.xlsx";
//2 調(diào)用easyexcel里面的方法實(shí)現(xiàn)寫操作
//write方法兩個(gè)參數(shù):第一個(gè)參數(shù)文件路徑名稱,第二個(gè)參數(shù)實(shí)體類class
EasyExcel.write(filename,DemoData.class).sheet("學(xué)生列表").doWrite(getData());
}
doWriter參數(shù)是一個(gè)list集合睡汹,所有我們需要?jiǎng)?chuàng)建一個(gè)list集合肴甸,將集合寫入到excel中
private static List<DemoData> getData() {
List<DemoData> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setSno(i);
data.setSname("lucy"+i);
list.add(data);
}
return list;
}
打開excel查看插入成功
image.png
讀操作:
讀操作是調(diào)用read方法,并且要傳入一個(gè)ReadListener參數(shù)
//實(shí)現(xiàn)excel讀操作
String filename = "E:\\write.xlsx";
EasyExcel.read(filename,DemoData.class,new ExcelListener()).sheet().doRead();
自己寫一個(gè)監(jiān)聽器囚巴,繼承AnalysisEventListener原在,查看源碼可知AnalysisEventListener實(shí)現(xiàn)了ReadListener接口
//一行一行讀取excel內(nèi)容
@Override
public void invoke(DemoData data, AnalysisContext analysisContext) {
System.out.println("****"+data);
}
//讀取表頭內(nèi)容
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
System.out.println("表頭:"+headMap);
}
//讀取完成之后
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) { }
}
運(yùn)行
image.png
使用easyexcel連接數(shù)據(jù)庫實(shí)現(xiàn)讀寫操作,實(shí)現(xiàn)分類
1.創(chuàng)建一個(gè)分類的excel文件彤叉,可以手動(dòng)創(chuàng)建庶柿,也可以使用代碼進(jìn)行操作
這里我使用代碼進(jìn)行插入
@Test
public void test() {
/*
1.創(chuàng)建一個(gè)文件
*/
String filename = "E:\\category.xlsx";
EasyExcel.write(filename, CategoryExcel.class).sheet("分類管理").doWrite(getList());
}
public static List<CategoryExcel> getList(){
List<CategoryExcel> list=new ArrayList<>();
CategoryExcel categoryExcel = new CategoryExcel("java學(xué)習(xí)","java編程");
CategoryExcel categoryExcel2 = new CategoryExcel("java學(xué)習(xí)","javaweb");
CategoryExcel categoryExcel3 = new CategoryExcel("框架","spring");
CategoryExcel categoryExcel4 = new CategoryExcel("框架","springmvc");
CategoryExcel categoryExcel5= new CategoryExcel("框架","mybatis");
list.add(categoryExcel);
list.add(categoryExcel2);
list.add(categoryExcel3);
list.add(categoryExcel4);
list.add(categoryExcel5);
return list;
}
插入完成
image.png
現(xiàn)在將數(shù)據(jù)插入到數(shù)據(jù)庫中
1.創(chuàng)建一個(gè)saveCategory方法進(jìn)行操作
@Autowired
private CategoryService categoryService;
@Test
void contextLoads() {
/*
2.把excel的數(shù)據(jù)信息存儲(chǔ)到數(shù)據(jù)庫里面
*/
File file=new File("E:\\category.xlsx");
categoryService.saveCategory(file,categoryService);
}
saveCategory方法
@Resource
private CategoryDao categoryDao;
@Override
public void save(Category category) {
categoryDao.save(category);
}
@Override
public void saveCategory(File file, CategoryService categoryService) {
try {
FileInputStream inputStream=new FileInputStream(file);
EasyExcel.read(inputStream, CategoryExcel.class,new CategoryListener(categoryService)).sheet().doRead();
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public Category getOne(String name, Integer pid) {
return categoryDao.getOne(name,pid);
}
CategoryListener監(jiān)聽器
public class CategoryListener extends AnalysisEventListener<CategoryExcel> {
//創(chuàng)建對(duì)象
public CategoryService categoryService;
public CategoryListener(){};
public CategoryListener(CategoryService categoryService){
this.categoryService=categoryService;
};
@Override
public void invoke(CategoryExcel categoryExcel, AnalysisContext analysisContext) {
if(categoryExcel == null) {
System.out.println("數(shù)據(jù)為空");
}
//一行一行讀取,每次讀取有兩個(gè)值秽浇,第一個(gè)值一級(jí)分類浮庐,第二個(gè)值二級(jí)分類
//判斷一級(jí)分類是否重復(fù)
Category category=existOne(categoryService,categoryExcel.getOneCategory());
if(category==null){
category=new Category(null,categoryExcel.getOneCategory(),0);
categoryService.save(category);
}
//獲取一級(jí)分類id值
Integer pid = category.getId();
//添加二級(jí)分類
//判斷二級(jí)分類是否重復(fù)
Category existTwoSubject = existTwo(categoryService, categoryExcel.getTwoCategory(), pid);
if(existTwoSubject == null) {
category=new Category(null,categoryExcel.getTwoCategory(),pid);
categoryService.save(category);
}
}
//判斷一級(jí)分類不能重復(fù)添加
//這里根據(jù)條件找到一級(jí)分類
private Category existOne(CategoryService categoryService , String name) {
Category category = categoryService.getOne(name,0);
return category;
}
//判斷二級(jí)分類不能重復(fù)添加
//這里根據(jù)條件找到二級(jí)分類
private Category existTwo(CategoryService categoryService,String name,Integer pid) {
Category category = categoryService.getOne(name,pid);
return category;
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
運(yùn)行結(jié)果
image.png