java如何实现excel导入数据功能?
在我们日常开发中,经常会遇到excel导入数据功能,如何实现?主要用到了org.apache.poi.xssf.usermodel.XSSFWorkbook类;下面上代码
controller层
@ApiOperation(value = "导入", notes = "导入")
@PostMapping("import")
public CommonResponse<Object> importData(@Validated ImportEntity importEntity) {
govFinInfoService.importData(importEntity);
return new CommonResponse<>(null);
}
实体类:
@Data
public class ImportEntity {
@NotNull(message = "上传文件不能为空!")
private MultipartFile attachment;
//导入类型,1:全量导入;0:增量导入
private String importType;
}
MultipartFile 类型接收前端传入的文件
service层:
@Override
public void importData(ImportEntity importEntity) {
List<String> columns = getColumns();
List<List<Object>> excelData = CommonUtils.getExcelData(importEntity,columns);
List<Integer> idList = govFinInfoDAO.queryIds();
govFinInfoDAO.importData(excelData);
//全量导入时 导入成功再删除之前的数据
if (ONE_OF_IMPORT_TYPE.equals(importEntity.getImportType()) && !idList.isEmpty()) {
govFinInfoDAO.deleteData(idList);
}
}
主要实现getExcelData:
public static List<List<Object>> getExcelData(ImportEntity importEntity, List<String> columns) {
//主要是做文件的校验
MultipartFile file = importEntity.getAttachment();
if (file.getSize() == 0) {
throw new ParamErrorAppException("请不要上传空文件!");
}
String filename = file.getOriginalFilename();
assert filename != null;
String suffix = filename.substring(filename.lastIndexOf('.') + 1).toLowerCase();
if (!"xlsx".equals(suffix)) {
throw new ParamErrorAppException("只能上传xlsx格式的文件!");
}
//文件校验end
List<List<Object>> dataList = new ArrayList<>();
try {
//这里主要用workBook类解析excel表格的数据
Workbook workbook = new XSSFWorkbook(file.getInputStream());
Sheet sheet = workbook.getSheetAt(0);
Row titleRow = sheet.getRow(0);
List<Object> titleData = getCellValue(null, titleRow);
if (!columns.toString().equals(titleData.toString())) {
throw new ParamErrorAppException("模板文件有误!");
}
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null) {
continue;
}
List<Object> rowData = getCellValue(columns.size(), row);
dataList.add(rowData);
}
} catch (Exception e) {
throw new ParamErrorAppException("数据异常,导入失败:" + e.getMessage());
}
return dataList;
}
这里主要是将excel数据解析成List<List<Object>>类型,内层List<Object>主要是每一行数据,
直接insert到数据库即可;当然也可以实现excel数据与实体类映射,思路是可以使用自定义注解
做映射。这边为了节约时间,直接使用了简单的写法。大家有兴趣可以尝试一下自定义注解做映射。
解析excel数据getCellValue:
private static List<Object> getCellValue(Integer columnSize, Row row) {
List<Object> rowData = new ArrayList<>();
columnSize = columnSize == null ? row.getLastCellNum() : columnSize;
for (int j = 0; j < columnSize; j++) {
Object value = null;
try {
Cell cell = row.getCell(j);
CellType cellTypeEnum = cell.getCellTypeEnum();
//数值类型
if (cellTypeEnum == CellType.NUMERIC) {
value = cell.getNumericCellValue();
} else {
//其他就string类型
value = cell.getStringCellValue();
value = StringUtils.isEmpty(value) ? null : value;
}
} catch (Exception e) {
log.error(e.getMessage());
}
rowData.add(value);
}
return rowData;
}
解析完数据后,insert到数据库中:
<insert id="importData">
insert into qc_gov_fin(<include refid="baseColumn"/>)
values
<foreach collection="list" item="row" separator=",">
(
<foreach collection="row" item="item" separator=",">
#{item}
</foreach>
)
</foreach>
</insert>
根据数据结构做了一个双重循环。
**注意:获取的数据顺序一定要跟你的数据库字段顺序保持一致!这也是不用实体类映射的弊端,需要人为控制插入字段顺序。**
至此,excel导入数据功能结束。
记录工作点滴,每日进步一点点~