本篇文章只记录EasyExcel的读(read)
首先看下EasyExcel解释:
EasyExcel是阿里巴巴开源的一个excel处理框架,是一个基于Java的简单、省内存的读写Excel的开源项目。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
开源地址:
github地址:https://github.com/alibaba/easyexcel
(光看代码我还是有点懵懵,到小破站搜了相关视频,狂神的一个视频直接解释得一清二楚。几乎直接照着他说的做就好了,当然了要根据自己的实际情况进行适当改动。)
我做的一个小项目需要把excel表中的数据导入到数据库中,然而有些数据列中还包含了很多数组对象[{…},{…},{…},{…}],而这里面的内容是要当成一个一个字段分别储存到数据库里的,因为人工或者excel都不太现实。所以就去了解了一下这个框架的使用。
excel如下:
注意:excel 不要有任何表头,因为是直接从实体类对应的参数列开始读取
<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
<version>2.2.6version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.75version>
dependency>
ps: 使用 @ExcelProperty 注解来说明对应的excel列
"电阻测试数据"对应的实体类
(这里需要说明一下,我当时在excel上把这4个参数名全部替换成了对应的英文名)
如果最后要存到数据库里的表结构 和 excel对应的实体类有出入(比如读取到的某个字段是数组对象结构如上图excel中的"电阻测试数据",那么还需要经过处理拆分成多个字段才能分开存入数据库),那就需要额外建立一个与数据库的表对应的类(略),用于接收所有数据并存入数据库中。
监听器具体实现
/**
* Date:2021/10/20
* Description: excel一行一行的回调监听器
*
* @author ivyhu
*/
@Component
public class DemoDataListener extends AnalysisEventListener<ExcelModel> {
@Resource
ChargingStationMapper charingStationResistanceReportMapper;
@Resource
CharingStationServiceImpl charingStationServiceImpl;
private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);
/**
* 有参构造
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
* @param serviceImpl
*/
public DemoDataListener(CharingStationServiceImpl serviceImpl) {
this.charingStationServiceImpl = serviceImpl;
}
//无参构造
public DemoDataListener() {
}
/**
* 读取数据或执行这个invoke()方法
* @param excelModel 类型
* @param context 分析器
*/
@Override
public void invoke(ExcelModel excelModel, AnalysisContext context) {
LOGGER.info("解析到一条数据:{}", JSON.toJSONString(excelModel));
//最终要保存到数据库的数据
ChargingStationModel reportModelData = new ChargingStationModel();
String productModelNum = "";
String itemNo = "";
Double groundResistance = 0.0;
Double insulationResistance = 0.0;
Byte type = 0;
Integer singlePilePower = 0;
/**
* 获取excel表中充电设施产品信息
*/
String str1 = excelModel.getInfoData();
JSONArray array1 = JSON.parseArray(str1);
//如果不为空,就解析[{},{},{},{}]类型的数组对象并获取值
if (!ObjectUtils.isEmpty(array1)) {
for (Object obj : array1) {
JSONObject jsonObject = (JSONObject) obj;
ChargingStationInfoDataExcelModel infoExcelModel = JSONObject.parseObject(String.valueOf((JSONObject) obj), ChargingStationInfoDataExcelModel.class);
type = infoExcelModel.getType();
singlePilePower = infoExcelModel.getSinglePilePower();
}
}
/**
* 获取excel表中电阻测试数据
*/
String str = excelModel.getResistanceData();
JSONArray array = JSON.parseArray(str);
//电阻测试数据不为空,就解析[{},{},{},{}]类型的数组对象并获取值
if (!ObjectUtils.isEmpty(array)) {
for (Object obj : array) {
JSONObject jsonObject = (JSONObject) obj;
ChargingStationResistanceDataExcelModel reportModel = JSONObject.parseObject(String.valueOf((JSONObject) obj), ChargingStationResistanceDataExcelModel.class);
productModelNum = reportModel.getProductModelNum();
itemNo = reportModel.getItemNo();
groundResistance = reportModel.getGroundResistance();
insulationResistance = reportModel.getInsulationResistance();
//插入数据到数据库
reportModelData = new ChargingStationModel(excelModel.getReportNo(), excelModel.getModelNum(), productModelNum, itemNo, groundResistance, insulationResistance, type, singlePilePower,
excelModel.getOutputVoltageControlErrorOfCharger(), excelModel.getOutputCurrentControlErrorOfCharger(), excelModel.getActiveStopChargeTestOutputCurrentStopRate(), excelModel.getPassiveStopChargeTestOutputCurrentStopRate(),
excelModel.getChargerOutputCurrentAdjustmentTimeAbove20A(), excelModel.getChargerOutputCurrentAdjustmentTimeUnder20A(), excelModel.getImpulseCurrent());
saveData(reportModelData);
}
}
}
/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
/*saveData();*/
LOGGER.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData(ChargingStationModel resistanceReportModel) {
//调用mapper插入数据库
charingStationServiceImpl.save(resistanceReportModel);
}
}
步骤三:调取监听器读取数据
1. Controller层
@RestController
@Controller
@RequestMapping("/product/charging_station")
public class ChargingStationController {
@Resource
CharingStationService charingStationService;
/**
* 提取excel表格数据的接口
*/
@PostMapping()
public void saveExcel(){
charingStationService.saveData();
}
}
2. Service层
@Service
public class CharingStationServiceImpl implements CharingStationService {
@Resource
ChargingStationMapper chargingStationMapper;
@Resource
ExcelUtil excelUtil;
@Resource
ChargingStationAcceptanceValueMapper chargingStationAcceptanceValueMapper;
/**
* 调用读取excel数据的方法
*/
@Override
public void saveData() {
excelUtil.excelRead();
}
3. 监听器入口
设置好文件地址、文件名、excel对应的实体类
@Component
public class ExcelUtil {
@Autowired
private CharingStationServiceImpl charingStationServiceImpl;
/**
* 最简单的读
* 1. 创建excel对应的实体对象 ExcelModel
* 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener}
* 3. 直接读即可
*/
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelUtil.class);
//文件位置
String PATH = "D:\\excelTest\\";
public void excelRead() {
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
String fileName = PATH + "充电桩验收测试数据.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
EasyExcel.read(fileName, ExcelModel.class, new DemoDataListener(charingStationServiceImpl)).sheet().doRead();
}
}
本文知识点:
JSONObject jsonObject = (JSONObject) obj;
ChargingStationResistanceDataExcelModel reportModel = JSONObject.parseObject(String.valueOf((JSONObject) obj);
@Component
public class DemoDataListener extends AnalysisEventListener<ExcelModel> {
...
}
//文件位置
String PATH = "D:\\excelTest\\";
public void excelRead() {
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
String fileName = PATH + "充电桩验收测试数据.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
EasyExcel.read(fileName, ExcelModel.class, new DemoDataListener(charingStationServiceImpl)).sheet().doRead();
}
ps: 一开始运行的时候报了几个错:
此文只是小菜鸡的一点点记录,有错望各位大佬指正!