前言
EasyExcel是一个基于Java的开源库,用于简化Excel文件的读写操作。它特别适用于处理大文件,因为它在读写过程中使用磁盘作为缓存,从而减少内存的使用,避免内存溢出问题。也是目前比较常用的解析Excel文件技术。作为开发者,对于怎么使用EasyExcel来完成数据导入、数据导出以及数据传输等任务还是有很大必要了解的。
Easy Excel 官方文档地址:
https://easyexcel.opensource.alibaba.com/docs/current/
使用EasyExcel解析Excel文件
public List<StudentData> readExcelToList(String filePath) {
try (InputStream inputStream = new FileInputStream(filePath)) {
// 读取 Excel 文件
ExcelDataListener importListener = new ExcelDataListener();
EasyExcelFactory.read(inputStream, StudentData.class, importListener).sheet().doRead();
return importListener.getDataList();
} catch (IOException e) {
e.printStackTrace();
}
return Collections.emptyList();
}
在解析Excel文件前,需要先自定义一个监听器。这里的ExcelDataListener 类和它的方法主要用来处理Excel文件解析过程中的数据,使得数据导入和导出变得更加可控和可定制。这种模式特别适用于需要对Excel文件中的数据进行复杂处理的应用程序。
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;
// 自定义的监听器,用于监听Excel解析过程中的事件。
public class ExcelDataListener extends AnalysisEventListener<StudentData> {
private List<StudentData> dataList = new ArrayList<>();
@Override
public void invoke(StudentData excelData, AnalysisContext analysisContext) {
dataList.add(excelData);
}
/**
* 可以在这里执行一些清理工作,或者处理解析后的数据,例如关闭资源、汇总数据、触发其他操作等
**/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
public List<StudentData> getDataList() {
return dataList;
}
}
处理解析的数据并保存成为TXT文件
List<StudentData> studentInfoList = readExcelToList("E:\\Example\\student.xlsx");
// 创建TXT文件
File studentFile = new File("E:\\Example\\latest_student.txt");
// 这里校验文件是否存在,存在则删除重新生成
if (file1.exists()) {
if (file1.delete()) {
System.out.println("文件已存在并删除成功,准备重新创建");
} else {
throw new ServiceException(CommCode.ERROR, "文件已存在,但无法删除");
}
}
String school = "第五小学";
for (StudentData data : studentInfoList) {
// 编写更新脚本
String updateSql = "UPDATE t_student" + " SET school=" + school + ", update_time =" + new Date()
+ " WHERE id =" + data.id + ";";
FileUtil.appendString(updateSql+ "\n", studentFile, CharsetUtil.UTF_8);
}
当然,也可以将数据处理后写入到一个新的Excel文件
public void writeToExcel(List<StudentData> dataList, String newFilePath) {
try {
List<ExcelDataOutVO> outInfoList = new ArrayList<>();
for (StudentData data : dataList) {
StudentData student = new StudentData();
student.setSchool("第五小学");
student.setUpdateTime(new Date());
outInfoList.add(excelDataOutVo);
}
EasyExcel.write(newFilePath, ExcelDataOutVO.class).sheet("Sheet1").needHead(false)
.doWrite(outInfoList);
} catch (Exception e) {
e.printStackTrace();
}
}
将数据导出成Excel
使用HttpServletResponse来直接向客户端浏览器发送Excel文件,让用户可以在浏览器中直接下载文件,而不需要通过文件系统。
public void exportExcel(HttpServletResponse response, List<StudentData> students) {
String fileName = "学生信息导出";
try {
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName + ".xlsx", "UTF-8"));
} catch (UnsupportedEncodingException ex) {
throw new ServiceException(CommCode.ERROR);
}
try {
EasyExcel.write(response.getOutputStream(), ExcelDataOutVO.class)
// 写第1个sheet
.sheet(fileName).doWrite(list);
} catch (Exception e) {
log.warn("-导出Excel异常", e.getMessage(), e);
throw new RuntimeException(e);
}
}
如果导出的数据过大,EasyExcel是支持处理大数据量并分割到多个Sheet页的,我们可以使用动态创建sheet来实现。
public void exportExcel(HttpServletResponse response, List<StudentData> students) {
String fileName = "学生信息导出";
try {
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName + ".xlsx", "UTF-8"));
} catch (UnsupportedEncodingException e) {
log.warn("-导出Excel异常: {}", e.getMessage(), e);
throw new RuntimeException(e);
}
// 计算需要创建的Sheet数量
int maxRowsPerSheet = 10000;
// 假设每个Sheet最大10000行
int sheetCount = (int) Math.ceil(students.size() / (double) maxRowsPerSheet);
try {
// 先创建第一个Sheet
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();
for (int i = 0; i < sheetCount; i++) {
// 创建新的Sheet,如果需要,可以为每个Sheet设置不同的名称或元数据
if (i > 0) {
writeSheet = EasyExcel.writerSheet("Sheet" + (i + 1)).build();
}
EasyExcel.write(response.getOutputStream(), ExcelDataOutVO.class)
.sheet(writeSheet)
.doWrite(students.subList(i * maxRowsPerSheet, Math.min((i + 1) * maxRowsPerSheet, students.size())));
}
} catch (Exception e) {
log.warn("-导出Excel异常: {}", e.getMessage(), e);
throw new RuntimeException(e);
}
}