导入Maven依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.7</version> </dependency>
|
Excel实体类
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ContentRowHeight; import com.alibaba.excel.annotation.write.style.HeadRowHeight; import com.alibaba.excel.metadata.BaseRowModel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data @NoArgsConstructor @AllArgsConstructor @Builder public class ExcelData extends BaseRowModel implements Serializable { @ExcelProperty("姓名") private String userName;
@ExcelProperty("职务") private String postName;
@ExcelProperty("籍贯") private String birthPlace; @ExcelProperty("出生日期") @DateTimeFormat("yyyy-MM-dd") private String birth;
@ExcelProperty("工资") @NumberFormat(".##") private String salary; }
|
- @ExcelProperty(value = String[], index = int):
设置表头信息
value: 表名称
index: 列号
可以根据名字或者Index去匹配。当然也可以不写,默认第一个字段就是index=0,以此类推。千万注意,要么全部不写,要么全部用index,要么全部用名字去匹配。千万别三个混着用,除非你非常了解源代码中三个混着用怎么去排序的。
ExcelIgnore
默认所有字段都会和excel去匹配,加了这个注解会忽略该字段
DateTimeFormat 日期转换,用String
去接收excel日期格式的数据会调用这个注解。里面的value参照java.text.SimpleDateFormat
ExcelIgnoreUnannotated 默认不加ExcelProperty
的注解的都会参与读写,加了不会参与
NumberFormat 数字转换,用String
去接收excel数字格式的数据会调用这个注解。里面的value参照java.text.DecimalFormat
监听器(每读取一行都会调用invoke方法)
package com.glriverside.qixing.personnel.listener;
import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.glriverside.qixing.personnel.config.ErrorMsg; import com.glriverside.qixing.personnel.common.ExcelData; import com.glriverside.qixing.personnel.model.Education; import com.glriverside.qixing.personnel.model.Post; import com.glriverside.qixing.personnel.model.User; import com.glriverside.qixing.personnel.service.EducationService; import com.glriverside.qixing.personnel.service.PostService; import com.glriverside.qixing.personnel.service.UserPostService; import com.glriverside.qixing.personnel.service.UserService; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.slf4j.Logger;
import java.util.List;
import static java.lang.invoke.MethodHandles.lookup; import static org.slf4j.LoggerFactory.getLogger;
@Data @NoArgsConstructor @AllArgsConstructor
public class ExcelListener<T> extends AnalysisEventListener<T> { private static final Logger LOG = getLogger(lookup().lookupClass());
private static final int BATCH_COUNT = 5;
private UserService userService;
private List<ErrorMsg> errorMsgList;
public ExcelListener(UserService userService, List<ErrorMsg> errorMsgList) { this.userService = userService; this.errorMsgList = errorMsgList; }
private List<User> userList = new ArrayList<>();
private T titleMap;
@Override public void invoke(T result, AnalysisContext context) { Integer rowIndex = context.readRowHolder().getRowIndex(); if (rowIndex == 0) { this.titleMap = result; } else { if (result instanceof ExcelData) { ExcelData excelData = (ExcelData)result; User user = new User();
int nameLength = excelData.getUserName().length(); if(excelData.getUserName() != null && nameLength < 5 && nameLength > 1) user.setName(excelData.getUserName()); else if (excelData.getUserName() == null ){ LOG.warn("数据为空! 第{}行, userName", rowIndex); errorMsgList.add(new ErrorMsg(rowIndex, "姓名为空")); } userService.addUser(user, false); } } LOG.info("解析数据第{}行,数据为:{}", rowIndex, result); if (list.size() >= BATCH_COUNT) { saveData(); list.clear(); } }
@Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { LOG.info("导入Excel完成"); saveData(); }
private void saveData() { LOG.info("{}条数据,开始存储数据库!", list.size()); demoDAO.save(list); LOG.info("存储数据库成功!"); } }
|
读取表头数据(需要的话在监听器中重写此方法即可)
@Override public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { LOGGER.info("解析到一条头数据:{}", JSON.toJSONString(headMap)); }
|
Controller层
读取单个Sheet
@RestController @RequestMapping("/import") public class ImportController { private static final Logger LOG = getLogger(lookup().lookupClass()); @PostMapping("/importExcel") public void importExcel(@RequestParam("file") MultipartFile file, HttpServletRequest request){ try { ExcelListener excelListener = new ExcelListener<ExcelData>();
EasyExcel.read(new BufferedInputStream(file.getInputStream()),excelListener).head(ExcelData.class).sheet().doReadSync(); } catch (Exception e) { LOG.error(e.getMessage(),e); } } }
|
读取多个Sheet
一次性读取
EasyExcel.read(new BufferedInputStream(file.getInputStream()), ExcelData.class, excelListener).doReadAll();
EasyExcel.read(new BufferedInputStream(file.getInputStream()),excelListener).head(ExcelData.class).doReadAll();
|
分批读取
@RestController @RequestMapping("/import") public class ImportController { private static final Logger LOG = getLogger(lookup().lookupClass()); @PostMapping("/importExcel") public void importExcel(@RequestParam("file") MultipartFile file, HttpServletRequest request){ ExcelReader excelReader = null; try { excelReader = EasyExcel.read(new BufferedInputStream(file.getInputStream())).build();
ReadSheet readSheet1 = EasyExcel.readSheet(0).head(ExcelData.class).registerReadListener(new ExcelListener()).build(); ReadSheet readSheet2 = EasyExcel.readSheet(1).head(ExcelData.class).registerReadListener(new ExcelListener()).build(); excelReader.read(readSheet1, readSheet2); } catch (Exception e) { LOG.error(e.getMessage(),e); } finally { if (excelReader != null) { excelReader.finish(); } } } }
|
Lambda表达式重构监听器(增加监听器的可扩展性)