1、读取Excel,暂只支持读取文件流方式,之后按需扩展
使用说明:现封装读取excel方法只支持读取业务规定的模版结构,第一列为中文表头,第二列是数据库字段,模版由前端提供,用户下载后填充数据。
默认读取第二列作为key(数据字段)。
实现方式:以行维度读取数据后组装集合,使用反射装配数据结构,返回泛型集合List
2、代码
<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
<version>3.1.2version>
dependency>
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.8.0version>
<scope>compilescope>
dependency>
/**
* excelReader监听器
*
* @author smallNorth_Lee
* @date 2022/12/1
*/
public class ExcelReadListener extends AnalysisEventListener<Map<Integer, String>> {
/**
* 表头数据(存储所有的表头数据)
*/
private final List<Map<Integer, String>> headList = new ArrayList<>();
/**
* 数据体
*/
private final List<Map<Integer, String>> dataList = new ArrayList<>();
/**
* 默认invoke从excel第二行开始读数据,第一行为中文表头,第二行为字段名称
* 如只需要从第一行读取,请使用invokeHeadMap方法
*/
@Override
public void invoke(Map<Integer, String> data, AnalysisContext analysisContext) {
if (1 == analysisContext.readRowHolder().getRowIndex()) {
headList.add(data);
} else {
dataList.add(data);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
public List<Map<Integer, String>> getHeadList() {
return headList;
}
public List<Map<Integer, String>> getDataList() {
return dataList;
}
}
/**
* 导出excel,支持全字段导入以及自定义字段导出
*
* @author smallNorth_Lee
* @date 2022/8/10
*/
public class EasyExcelUtil {
/**
* 读取excel模版数据
*
* @param file 文件流
* @param target 转换对象
* @param 泛型结构
* @return List
*/
public static <T> List<T> readExcel(MultipartFile file, Class<T> target) {
try {
ExcelReadListener excelReadListener = new ExcelReadListener();
EasyExcelFactory.read(file.getInputStream(), excelReadListener).sheet().doRead();
List<Map<Integer, String>> headList = excelReadListener.getHeadList();
if (CollectionUtils.isEmpty(headList)) {
throw new RuntimeException("表格中未包含表头信息!");
}
List<Map<Integer, String>> dataList = excelReadListener.getDataList();
if (CollectionUtils.isEmpty(dataList)) {
throw new RuntimeException("表格中包含错误数据,请调整后上传!");
}
//封装数据体
List<Map<String, Object>> excelDataList = new ArrayList<>();
for (Map<Integer, String> headMap : headList) {
for (Map<Integer, String> dataRow : dataList) {
Map<String, Object> rowData = new LinkedHashMap<>();
headMap.forEach((key, value) -> rowData.put(value, dataRow.get(key)));
excelDataList.add(rowData);
}
}
//字段转驼峰
excelDataList = excelDataList.stream().map(MapUtil::toCamelCaseMap).collect(Collectors.toList());
return ConvertUtils.setList(excelDataList, target);
} catch (IOException e) {
e.printStackTrace();
}
return Collections.emptyList();
}
}
/**
* 类型转换器
*
*/
public class ConvertUtils {
/**
* List
public static <T> List<T> setList(List<Map<String, Object>> srcList, Class<T> clazz) {
List<T> list = new ArrayList<>();
srcList.forEach(x -> {
try {
T t = clazz.newInstance();
Field[] fields = t.getClass().getDeclaredFields();
for (Field field : fields) {
if (!"serialVersionUID".equals(field.getName())) {
//设置对象的访问权限,保证对private的属性的访问
field.setAccessible(true);
//读取配置转换字段名,并从map中取出数据
Object v = x.get(field.getName());
field.set(t, convert(v, field.getType()));
}
}
list.add(t);
} catch (Exception e) {
}
});
return list;
}
}
@ApiOperation(value = "读取excel")
@PostMapping("/reader/excel")
public ResultVo<List<ExcelFieldDemo>> readExcel(@RequestBody MultipartFile file) {
List<ExcelFieldDemo> readExcelList = EasyExcelUtil.readExcel(file, ExcelFieldDemo.class);
//入库或其它业务操作
return new ResultVo<>(readExcelList);
}