依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.6</version>
</dependency>
EasyExcelUtil
public class EasyExcelUtil {
/**
* 同步无模型读(默认读取sheet0,从第2行开始读)
* @param filePath excel文件的绝对路径
*/
public static List<Map<Integer, String>> syncRead(String filePath){
return EasyExcelFactory.read(filePath).sheet().doReadSync();
}
/**
* 同步无模型读(自定义读取sheetX,从第2行开始读)
* @param filePath excel文件的绝对路径
* @param sheetNo sheet页号,从0开始
*/
public static List<Map<Integer, String>> syncRead(String filePath, Integer sheetNo){
return EasyExcelFactory.read(filePath).sheet(sheetNo).doReadSync();
}
/**
* 同步无模型读(指定sheet和表头占的行数)
* @param filePath
* @param sheetNo sheet页号,从0开始
* @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
*/
public static List<Map<Integer, String>> syncRead(String filePath, Integer sheetNo, Integer headRowNum){
return EasyExcelFactory.read(filePath).sheet(sheetNo).headRowNumber(headRowNum).doReadSync();
}
/**
* 同步无模型读(指定sheet和表头占的行数)
* @param inputStream
* @param sheetNo sheet页号,从0开始
* @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
*/
public static List<Map<Integer, String>> syncRead(InputStream inputStream, Integer sheetNo, Integer headRowNum){
return EasyExcelFactory.read(inputStream).sheet(sheetNo).headRowNumber(headRowNum).doReadSync();
}
/**
* 同步无模型读(指定sheet和表头占的行数)
* @param file
* @param sheetNo sheet页号,从0开始
* @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
*/
public static List<Map<Integer, String>> syncRead(File file, Integer sheetNo, Integer headRowNum){
return EasyExcelFactory.read(file).sheet(sheetNo).headRowNumber(headRowNum).doReadSync();
}
/**
* 同步按模型读(默认读取sheet0,从第2行开始读)
* @param filePath
* @param clazz 模型的类类型(excel数据会按该类型转换成对象)
*/
public static List<T> syncReadModel(String filePath, Class clazz){
return EasyExcelFactory.read(filePath).sheet().head(clazz).doReadSync();
}
/**
* 同步按模型读(默认表头占一行,从第2行开始读)
* @param filePath
* @param clazz 模型的类类型(excel数据会按该类型转换成对象)
* @param sheetNo sheet页号,从0开始
*/
public static List<T> syncReadModel(String filePath, Class clazz, Integer sheetNo){
return EasyExcelFactory.read(filePath).sheet(sheetNo).head(clazz).doReadSync();
}
/**
* 同步按模型读(指定sheet和表头占的行数)
* @param inputStream
* @param clazz 模型的类类型(excel数据会按该类型转换成对象)
* @param sheetNo sheet页号,从0开始
* @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
*/
public static List<ExcelWeldingData> syncReadModel(InputStream inputStream, Class clazz, Integer sheetNo, Integer headRowNum){
return EasyExcelFactory.read(inputStream).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync();
}
/**
* 同步按模型读(指定sheet和表头占的行数)
* @param file
* @param clazz 模型的类类型(excel数据会按该类型转换成对象)
* @param sheetNo sheet页号,从0开始
* @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
*/
public static List<T> syncReadModel(File file, Class clazz, Integer sheetNo, Integer headRowNum){
return EasyExcelFactory.read(file).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync();
}
/**
* 同步按模型读(指定sheet和表头占的行数)
* @param filePath
* @param clazz 模型的类类型(excel数据会按该类型转换成对象)
* @param sheetNo sheet页号,从0开始
* @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
*/
public static List<T> syncReadModel(String filePath, Class clazz, Integer sheetNo, Integer headRowNum){
return EasyExcelFactory.read(filePath).sheet(sheetNo).headRowNumber(headRowNum).head(clazz).doReadSync();
}
/**
* 异步无模型读(默认读取sheet0,从第2行开始读)
* @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
* @param filePath 表头占的行数,从0开始(如果要连表头一起读出来则传0)
*/
public static void asyncRead(String filePath, AnalysisEventListener<T> excelListener){
EasyExcelFactory.read(filePath, excelListener).sheet().doRead();
}
/**
* 异步无模型读(默认表头占一行,从第2行开始读)
* @param filePath 表头占的行数,从0开始(如果要连表头一起读出来则传0)
* @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
* @param sheetNo sheet页号,从0开始
*/
public static void asyncRead(String filePath, AnalysisEventListener<T> excelListener, Integer sheetNo){
EasyExcelFactory.read(filePath, excelListener).sheet(sheetNo).doRead();
}
/**
* 异步无模型读(指定sheet和表头占的行数)
* @param inputStream
* @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
* @param sheetNo sheet页号,从0开始
* @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
*/
public static void asyncRead(InputStream inputStream, AnalysisEventListener<T> excelListener, Integer sheetNo, Integer headRowNum){
EasyExcelFactory.read(inputStream, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead();
}
/**
* 异步无模型读(指定sheet和表头占的行数)
* @param file
* @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
* @param sheetNo sheet页号,从0开始
* @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
*/
public static void asyncRead(File file, AnalysisEventListener<T> excelListener, Integer sheetNo, Integer headRowNum){
EasyExcelFactory.read(file, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead();
}
/**
* 异步无模型读(指定sheet和表头占的行数)
* @param filePath
* @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
* @param sheetNo sheet页号,从0开始
* @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
* @return
*/
public static void asyncRead(String filePath, AnalysisEventListener<T> excelListener, Integer sheetNo, Integer headRowNum){
EasyExcelFactory.read(filePath, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead();
}
/**
* 异步按模型读取(默认读取sheet0,从第2行开始读)
* @param filePath
* @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
* @param clazz 模型的类类型(excel数据会按该类型转换成对象)
*/
public static void asyncReadModel(String filePath, AnalysisEventListener<ExcelWeldingData> excelListener, Class clazz){
EasyExcelFactory.read(filePath, clazz, excelListener).sheet().doRead();
}
/**
* 异步按模型读取(默认表头占一行,从第2行开始读)
* @param filePath
* @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
* @param clazz 模型的类类型(excel数据会按该类型转换成对象)
* @param sheetNo sheet页号,从0开始
*/
public static void asyncReadModel(String filePath, AnalysisEventListener<T> excelListener, Class clazz, Integer sheetNo){
EasyExcelFactory.read(filePath, clazz, excelListener).sheet(sheetNo).doRead();
}
/**
* 异步按模型读取
* @param inputStream
* @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
* @param clazz 模型的类类型(excel数据会按该类型转换成对象)
* @param sheetNo sheet页号,从0开始
* @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
*/
public static void asyncReadModel(InputStream inputStream, AnalysisEventListener<ExcelWeldingData> excelListener, Class clazz, Integer sheetNo, Integer headRowNum){
EasyExcelFactory.read(inputStream, clazz, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead();
}
/**
* 异步按模型读取
* @param file
* @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
* @param clazz 模型的类类型(excel数据会按该类型转换成对象)
* @param sheetNo sheet页号,从0开始
* @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
*/
public static void asyncReadModel(File file, AnalysisEventListener<T> excelListener, Class clazz, Integer sheetNo, Integer headRowNum){
EasyExcelFactory.read(file, clazz, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead();
}
/**
* 异步按模型读取
* @param filePath
* @param excelListener 监听器,在监听器中可以处理行数据LinkedHashMap,表头数据,异常处理等
* @param clazz 模型的类类型(excel数据会按该类型转换成对象)
* @param sheetNo sheet页号,从0开始
* @param headRowNum 表头占的行数,从0开始(如果要连表头一起读出来则传0)
*/
public static void asyncReadModel(String filePath, AnalysisEventListener<T> excelListener, Class clazz, Integer sheetNo, Integer headRowNum){
EasyExcelFactory.read(filePath, clazz, excelListener).sheet(sheetNo).headRowNumber(headRowNum).doRead();
}
/**
* 无模板写文件
* @param filePath
* @param head 表头数据
* @param data 表内容数据
*/
public static void write(String filePath, List<List<String>> head, List<List<Object>> data){
EasyExcel.write(filePath).head(head).sheet().doWrite(data);
}
/**
* 无模板写文件
* @param filePath
* @param head 表头数据
* @param data 表内容数据
* @param sheetNo sheet页号,从0开始
* @param sheetName sheet名称
*/
public static void write(String filePath, List<List<String>> head, List<List<Object>> data, Integer sheetNo, String sheetName){
EasyExcel.write(filePath).head(head).sheet(sheetNo, sheetName).doWrite(data);
}
/**
* 根据excel模板文件写入文件
* @param filePath
* @param templateFileName
* @param headClazz
* @param data
*/
public static void writeTemplate(HttpServletResponse response, String filePath, String templateFileName, Class headClazz, List data) throws IOException {
ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), headClazz).withTemplate(templateFileName).build();
WriteSheet sheet = EasyExcel.writerSheet().build();
excelWriter.fill(data,sheet);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
try {
String fileName = URLEncoder.encode(filePath, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
excelWriter.finish();
} catch (Exception e) {
e.printStackTrace();
// 重置response
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
Map<String, String> map = new HashMap<String, String>();
map.put("status", "failure");
map.put("message", "下载文件失败" + e.getMessage());
response.getWriter().println(JSON.toJSONString(map));
}
}
/**
* 根据excel模板文件写入文件
* @param filePath
* @param templateFileName
* @param headClazz
* @param data
*/
public static void writeTemplate(String filePath, String templateFileName, Class headClazz, List data){
ExcelWriter excelWriter = EasyExcel.write(filePath, headClazz).withTemplate(templateFileName).build();
WriteSheet sheet = EasyExcel.writerSheet().build();
excelWriter.fill(data,sheet);
excelWriter.finish();
}
/**
* 根据excel模板文件写入文件
* @param filePath 保存路径
* @param templateFileName 模板路径
* @param data
*/
public static void writeTemplate(String filePath, String templateFileName, List data){
ExcelWriter excelWriter = EasyExcel.write(filePath).withTemplate(templateFileName).build();
WriteSheet sheet = EasyExcel.writerSheet().build();
excelWriter.fill(data,sheet);
excelWriter.finish();
}
/**
* 按模板写文件
* @param filePath
* @param headClazz 表头模板
* @param data 数据
*/
public static void write(String filePath, Class headClazz, List data){
EasyExcel.write(filePath, headClazz).sheet().doWrite(data);
}
/**
* 按模板写文件
* @param filePath
* @param headClazz 表头模板
* @param data 数据
* @param sheetNo sheet页号,从0开始
* @param sheetName sheet名称
*/
public static void write(String filePath, Class headClazz, List data, Integer sheetNo, String sheetName){
EasyExcel.write(filePath, headClazz).sheet(sheetNo, sheetName).doWrite(data);
}
/**
* 按模板写文件
* @param filePath
* @param headClazz 表头模板
* @param data 数据
* @param writeHandler 自定义的处理器,比如设置table样式,设置超链接、单元格下拉框等等功能都可以通过这个实现(需要注册多个则自己通过链式去调用)
* @param sheetNo sheet页号,从0开始
* @param sheetName sheet名称
*/
public static void write(String filePath, Class headClazz, List data, WriteHandler writeHandler, Integer sheetNo, String sheetName){
EasyExcel.write(filePath, headClazz).registerWriteHandler(writeHandler).sheet(sheetNo, sheetName).doWrite(data);
}
/**
* 按模板写文件(包含某些字段)
* @param filePath
* @param headClazz 表头模板
* @param data 数据
* @param includeCols 包含字段集合,根据字段名称显示
* @param sheetNo sheet页号,从0开始
* @param sheetName sheet名称
*/
public static void writeInclude(String filePath, Class headClazz, List data, Set<String> includeCols, Integer sheetNo, String sheetName){
EasyExcel.write(filePath, headClazz).includeColumnFiledNames(includeCols).sheet(sheetNo, sheetName).doWrite(data);
}
/**
* 按模板写文件(排除某些字段)
* @param filePath
* @param headClazz 表头模板
* @param data 数据
* @param excludeCols 过滤排除的字段,根据字段名称过滤
* @param sheetNo sheet页号,从0开始
* @param sheetName sheet名称
*/
public static void writeExclude(String filePath, Class headClazz, List data, Set<String> excludeCols, Integer sheetNo, String sheetName){
EasyExcel.write(filePath, headClazz).excludeColumnFiledNames(excludeCols).sheet(sheetNo, sheetName).doWrite(data);
}
/**
* 读取本地excel模板文件内容
* @param localFilePath 本地文件路径
* @return List<Map<Integer, Object>>
*/
public static List<Map<Integer, Object>> getLocalModelContent(String localFilePath) {
// 通过表头校验上传的excel是否正确
ClassPathResource classPathResource = new ClassPathResource(localFilePath);
InputStream stream = null;
try {
stream = classPathResource.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
return EasyExcelUtil.syncRead(stream, 0, 0);
}
/**
* 校验上传的excel文件是否正确
* @param model 本地模板文件内容
* @param read 上传文件内容
* @return Object
*/
public static List<Map<Integer, Object>> checkModel(List<Map<Integer, Object>> model,List<Map<Integer, Object>> read) {
List<Map<Integer, Object>> list = new ArrayList<>();
Map<Integer, Object> map = new HashMap<>(4);
if (ObjectUtils.isEmpty(model)){
map.put(500, "本地模板文件错误");
list.add(map);
return list;
}
int size = read.size();
int size1 = model.size();
if (size < size1){
map.put(500, "导入的EXCEL文件错误,请选择正确的文件进行上传");
list.add(map);
return list;
}
if (size == size1){
map.put(500, "导入的EXCEL文件为空,请填写数据进行上传");
list.add(map);
return list;
}
List<Map<Integer, Object>> maps = read.subList(0, model.size());
StringBuilder str = new StringBuilder("");
for (Map<Integer, Object> mode : model) {
for (Map<Integer, Object> red : maps) {
mode.forEach((k, v) ->{
if (v != null || red.get(k) != null){
boolean map1 = v == null && red.get(k) != null;
if (map1){
str.append("{第").append(k + 1).append("列的表头不存在").append("\r\n");
}
assert v != null;
if (!v.equals(red.get(k))){
if (null == red.get(k)){
str.append("{第").append(k + 1).append("列的表头").append("应为[").append(v).append("]}").append("\r\n");
}else{
str.append("{第").append(k + 1).append("列的表头").append(red.get(k)).append("应为[").append(v).append("]}").append("\r\n");
}
}
}
});
if (!ObjectUtils.isEmpty(str)){
map.put(500, "导入的EXCEL文件错误,请选择正确的文件进行上传");
list.add(map);
return list;
}
}
}
read.subList(0, model.size()).clear();
return read;
}
}
异步监听器
@AllArgsConstructor
@NoArgsConstructor
public class DefaultExcelListener<T> extends AnalysisEventListener<T> {
List<T> list = new ArrayList<>();
@Override
public void invoke(T data, AnalysisContext context) {
list.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
}
}