为什么要使用EsayExcel?
因为在线下活动推过过程中,活动的营运人员会收到许多的手机号,个人信息,不可能让营运人员一个一个的录入,最多整理为一个Excel表格,然后在系统中进行上传,而此功能的实现需要批量的导入excel中的数据到我们的数据库中
信息如下表格
姓名 | 手机号 | 性别 | 活动编号 |
什么是EasyExcel
EasyExcel是一个基于Java的简单,省内存的读写Excel的开源项目.尽可能节约内存的情况下支持读写百M的Excel.
github地址:https://github.com/alibaba/easyexcel
目前EasyExcel的
2+版本支持Java7和Java6
3+版本至少需要Java8
如何使用EasyExcel
EasyExcel文档地址 https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read
依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>
EasyExcel如何读取Excel
根据excel里面的内容创建对应的实体类
创建对应的监听类,并且实现ReadListener接口并且需要在监听器内,invoke方法和doAfterAllAnalysed方法,其中invoke方法当EasyExcel解析了一条数据后就会执行,doAfterAllAnalysed方法,在所有数据都解析完成后执行
官方也提供了多种方式与Excel对应的列对应上
@Getter
@Setter
@EqualsAndHashCode
public class IndexOrNameData {
/**
* 强制读取第三个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
*/
@ExcelProperty(index = 2)
private Double doubleData;
/**
* 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据
*/
@ExcelProperty("字符串标题")
private String string;
@ExcelProperty("日期标题")
private Date date;
}
编写监听器继承AnalysisEventListener
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
@Slf4j
public class DemoDataListener implements ReadListener<DemoData> {
/**
* 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 100;
/**
* 缓存的数据
*/
private List<DemoData> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
/**
* 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
*/
private DemoDAO demoDAO;
public DemoDataListener() {
// 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
demoDAO = new DemoDAO();
}
/**
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
*
* @param demoDAO
*/
public DemoDataListener(DemoDAO demoDAO) {
this.demoDAO = demoDAO;
}
/**
* 这个每一条数据解析都会来调用
*
* @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
@Override
public void invoke(DemoData data, AnalysisContext context) {
log.info("解析到一条数据:{}", JSON.toJSONString(data));
cachedDataList.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (cachedDataList.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
}
}
/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
log.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
log.info("{}条数据,开始存储数据库!", cachedDataList.size());
demoDAO.save(cachedDataList);
log.info("存储数据库成功!");
}
}
代码实现
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@ExcelProperty("ID")
private Integer id;
@ExcelProperty("姓名")
private String name;
@ExcelProperty("年龄")
private Integer age;
@ExcelProperty("性别")
private String gender;
}
public class DataReadListener extends AnalysisEventListener<User> {
@Override
public void invoke(User user, AnalysisContext analysisContext) {
System.out.println("invoke");
System.out.println(user);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
System.out.println("doAfterAllAnalysed");
}
}
public class DemoEasyExcel {
public static void main(String[] args) {
EasyExcel.read(new File("D:\\yum\\笑傲江湖.xlsx"),new DataReadListener()).head(User.class).sheet(0).doRead();
}
}
excel文件中的数据
代码运行结束后的结果
如何写Excel
我们继续使用之前的User类
public class WriteDemoEasyExcel {
public static void main(String[] args) {
EasyExcel.write(new File("D:\\yum\\明教.xlsx"), User.class).sheet("笑傲江湖").doWrite(getData());
}
private static List<User> getData() {
List<User> userList = new ArrayList<>();
userList.add(new User(1,"白眉鹰王", 58, "男"));
userList.add(new User(2,"青翼蝠王", 45, "男"));
userList.add(new User(3,"金毛狮王", 55, "男"));
userList.add(new User(4,"紫衫龙王", 48, "女"));
return userList;
}
}
结果展示