最近在开发中,有使用excel上传数据的功能需要实现,在实现过后,再次进行记录并分享。
1.场景分析
医院给院内设备批量录入设备使用记录数据,若一条一条录则太过麻烦,于是excel上传需求产生。
2.技术选型
采用springBoot+Java8,依赖为:
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency>
3.代码
3.1后端:
//指定处理POST请求的接口路径为"/excelUpload"
@PostMapping("excelUpload")
public Result excelUpload(@RequestParam("file") MultipartFile file) throws IOException {
//打印文件名和文件大小
System.out.println(file.getOriginalFilename());
System.out.println(file.getSize());
//创建java对象的集合类,用于接收excel数据
ArrayList<excelUploadCustomLoggingDataDto> excelUploadCustomLoggingDataDtos = new ArrayList();
//getWorkbook方法处理文件是xlsx或xls的情况
InputStream inputStream = file.getInputStream();
Workbook workbook = getWorkbook(inputStream);
if (workbook != null) {//判断Workbook对象是否成功创建,确保处理的文件是Excel格式。
Sheet sheet = workbook.getSheetAt(0); // 假设数据在第一个Sheet中,也就是这个上传的excel文件内的第一个页面
Iterator<Row> iterator = sheet.iterator();//创建行的迭代器。
if (iterator.hasNext()) {检查是否有行数据
// 处理标题行,获取列索引
Row headerRow = iterator.next();//获取第一行数据,即标题行
//findColumnIndex:找到指定列的索引
int deviceIndex = findColumnIndex(headerRow, "设备生产编号");
int hospitalIndex = findColumnIndex(headerRow, "医院编订号");
int quantityIndex = findColumnIndex(headerRow, "使用数量");
int timeIndex = findColumnIndex(headerRow, "采集时间");
while (iterator.hasNext()) {//遍历除标题行之外的所有行。
Row currentRow = iterator.next();
// 使用列索引获取对应列的值
//获取生产编号
String facilityProductionNumber = getCellValue(currentRow.getCell(deviceIndex));
//获取医院编订号
String hospitalScheduledNumber = getCellValue(currentRow.getCell(hospitalIndex));
//获取使用数量
String useCount = getCellValue(currentRow.getCell(quantityIndex));
//获取采集时间
String dataTime = getCellValue(currentRow.getCell(timeIndex));
// 创建对象并添加到列表
excelUploadCustomLoggingDataDto obj = new excelUploadCustomLoggingDataDto(facilityProductionNumber, hospitalScheduledNumber, dataTime,useCount);
excelUploadCustomLoggingDataDtos.add(obj);
}
}
workbook.close();
}
System.out.println("excel上传完成");
//此处我的需求是在前端进行展示而不是直接存储数据库,所以返回给前端
return Result.success(excelUploadCustomLoggingDataDtos);
}
private static Workbook getWorkbook(InputStream inputStream) throws IOException {
try {
return new XSSFWorkbook(inputStream); // 尝试解析为xlsx格式
} catch (Exception e) {
// 如果解析失败,尝试解析为xls格式
return new HSSFWorkbook(inputStream);
}
}
//根据excel中单元格类型不同调用不同方法获取值,可根据自己内容做修改
private static String getCellValue(Cell cell) {
if (cell == null) {
return ""; // 处理空单元格
}
switch (cell.getCellType()) {
case Cell.CELL_TYPE_STRING:
return cell.getStringCellValue();
case Cell.CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
// 处理日期类型
return cell.getDateCellValue().toString();
} else {
// 处理普通数字类型
DataFormatter dataFormatter = new DataFormatter();
return dataFormatter.formatCellValue(cell);
}
default:
return "";
}
}
private static int findColumnIndex(Row headerRow, String columnName) {
Iterator<Cell> cellIterator = headerRow.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
if (cell.getStringCellValue().equals(columnName)) {
return cell.getColumnIndex();
}
}
return -1; // 列不存在
}
3.2前端
采用的是layu的上传组件
//excel上传
upload.render({
elem: '#excelUpload', // 绑定上传按钮
url: '${pageContext.request.contextPath}/customLoggingDataInfo/excelUpload',
accept: 'file', // 普通文件
exts:'xls|xlsx',
done: function(res){//成功回调
console.log("res",res);
if(res.code==200){
dataList=[]
res.data.forEach((element)=>{
element.hospitalId=hospitalAccount.hospitalId
dataList.push(element)
})
updateDataList()//数据刷新至页面
}else{
layer.msg(res.message)
}
}
});
4.excel等展示
这是以上代码对应的excel格式
上传后前端显示如下:
总体就是这样,如有遗漏,请指出。