前后端分离,Excel导入
程序员文章站
2022-03-15 12:36:12
...
Excel的导入和导出也是比较常见的需求,Excel导入之前写过了,可参考:前后端分离,Excel导出实现,现在看看Excel导入如何实现,先大概说一下思路:
(1)首先,最好限制Excel中输入的数据的,提供一个导入的模板(这里暂时没做)
(2)读取Excel导入的数据,难点是怎样解析数据
前端代码:
<el-upload class="upload-demo"
:action="uploadUrl2"
:before-upload="handleBeforeUpload2"
:on-error="handleUploadError"
:before-remove="beforeRemove"
multiple
:limit="1"
:on-exceed="handleExceed"
accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
:file-list="fileList">
<el-button size="small" type="primary">批量导入用户</el-button>
</el-upload>
声明相应的属性和方法:
uploadUrl2: 'http://192.168.43.152:8089/user/import',
fileList: [],
第一个是导入的路径
第二个是接收文件的数组,其实这里应该限定一个,毕竟导入数据,几个文件一起导入的可能性比较小
这里主要看handleBeforeUpload2(file)方法,其他两个方法主要是限制和提示作用:
//导入
handleBeforeUpload2(file){
debugger
this.fileTemp = file
let fileName = file.name
let fileType = fileName.substring(fileName.lastIndexOf('.') + 1);
// 判断上传文件格式
if (this.fileTemp) {
if ((fileType != 'xlsx') && (fileType != 'xls')) {
this.$message({
type: 'warning',
message: '附件格式错误,请删除后重新上传!'
})
return;
}
} else {
this.$message({
type: 'warning',
message: '请上传附件!'
})
return;
}
this.uploadUrl = 'http://192.168.43.152:8089/user/import'
console.log("开始上传,上传的文件为:"+file)
let formData = new FormData();
formData.append("multipartFiles", file);
axios({
method: 'post',
url: 'http://192.168.43.152:8089/user/import',
data: formData,
headers: {'Content-Type': 'multipart/form-data' }
}).then((res) => {
console.log("文件上传返回:"+res)
}).catch(error => {
console.log("文件上传异常:"+error)
})
// this.uploadUrl ='http://192.168.43.152:8089/file/upload'
},
后端代码:
这里使用的是POI:
/**
* 批量导入用户
*
*/
@RequestMapping(value = "/import")
@ResponseBody
public Object ExcelImport(MultipartFile[] multipartFiles) throws Exception {
if (multipartFiles == null || multipartFiles.length < 1){
return ResultUtil.result(EnumCode.INTERNAL_SERVER_ERROR.getValue(),"空数据,导入失败");
}
for (MultipartFile file : multipartFiles){
List<String[]> list = ExcelUtil.readExcel(file);
if (list.isEmpty()){
return ResultUtil.result(EnumCode.INTERNAL_SERVER_ERROR.getValue(),"空数据,导入失败");
}
for (int i=0;i<list.size();i++){
String[] values = list.get(i);
//这里只导入了3列数据:姓名、邮箱和是否可用(0、1),其他列可自行导入,现转换格式再写入数据库,比如:
//导入角色的时候,根据角色名称查找角色id,如果角色id不存在,可以默认为学生之类的处理
User user = new User();
user.setUsername(values[0]);
user.setEmail(values[1]);
user.setEnable(values[2] == null ? 1 : Integer.valueOf(values[2]));
user.setCreateTime(new Date());
user.setId(UUID.randomUUID().toString().replace("-",""));
user.setPassword("a123456");
user.setRoleId("3");
userService.addUser(user);
}
}
//前端可以通过状态码,判断文件是否上传成功
return ResultUtil.result(EnumCode.OK.getValue(),"文件上传成功");
}
其中,读取Excel数据的方法ExcelUtil.readExcel(file),完整代码如下:
/**
* 读入excel文件,解析后返回
* @param file
* @throws IOException
*/
public static List<String[]> readExcel(MultipartFile file) throws IOException {
//检查文件
checkFile(file);
//获得Workbook工作薄对象
Workbook workbook = getWorkBook(file);
//创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回
List<String[]> list = new ArrayList<String[]>();
if(workbook != null){
for(int sheetNum = 0;sheetNum < workbook.getNumberOfSheets();sheetNum++){
//获得当前sheet工作表
org.apache.poi.ss.usermodel.Sheet sheet = workbook.getSheetAt(sheetNum);
if(sheet == null){
continue;
}
//获得当前sheet的开始行
int firstRowNum = sheet.getFirstRowNum();
//获得当前sheet的结束行
int lastRowNum = sheet.getLastRowNum();
//循环除了第一行的所有行
for(int rowNum = firstRowNum+1;rowNum <= lastRowNum;rowNum++){
//获得当前行
Row row = sheet.getRow(rowNum);
if(row == null){
continue;
}
//获得当前行的开始列
int firstCellNum = row.getFirstCellNum();
//获得当前行的列数
int lastCellNum = row.getPhysicalNumberOfCells();
String[] cells = new String[row.getPhysicalNumberOfCells()];
//循环当前行
for(int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++){
Cell cell = row.getCell(cellNum);
cells[cellNum] = getCellValue(cell);
}
list.add(cells);
}
// workbook.cloneSheet(sheetNum);
}
// workbook.close();
}
return list;
}
public static void checkFile(MultipartFile file) throws IOException{
//判断文件是否存在
if(null == file){
System.out.println("文件不存在!");
throw new FileNotFoundException("文件不存在!");
}
//获得文件名
String fileName = file.getOriginalFilename();
//判断文件是否是excel文件
if(!fileName.endsWith(xls) && !fileName.endsWith(xlsx)){
System.out.println(fileName + "不是excel文件");
throw new IOException(fileName + "不是excel文件");
}
}
public static Workbook getWorkBook(MultipartFile file) {
//获得文件名
String fileName = file.getOriginalFilename();
//创建Workbook工作薄对象,表示整个excel
Workbook workbook = null;
try {
//获取excel文件的io流
InputStream is = file.getInputStream();
//根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象
if(fileName.endsWith(xls)){
//2003
workbook = new HSSFWorkbook(is);
}else if(fileName.endsWith(xlsx)){
//2007
workbook = new XSSFWorkbook(is);
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
return workbook;
}
public static String getCellValue(Cell cell){
String cellValue = "";
if(cell == null){
return cellValue;
}
//把数字当成String来读,避免出现1读成1.0的情况
if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
cell.setCellType(Cell.CELL_TYPE_STRING);
}
//判断数据的类型
switch (cell.getCellType()){
case Cell.CELL_TYPE_NUMERIC: //数字
cellValue = String.valueOf(cell.getNumericCellValue());
break;
case Cell.CELL_TYPE_STRING: //字符串
cellValue = String.valueOf(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_BOOLEAN: //Boolean
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_FORMULA: //公式
cellValue = String.valueOf(cell.getCellFormula());
break;
case Cell.CELL_TYPE_BLANK: //空值
cellValue = "";
break;
case Cell.CELL_TYPE_ERROR: //故障
cellValue = "非法字符";
break;
default:
cellValue = "未知类型";
break;
}
return cellValue;
}
推荐阅读
-
Springboot实现前后端分离excel下载
-
Springboot实现前后端分离excel下载
-
laravel+vue 前后端分离开发excel导出
-
前后端分离,Excel导入
-
vue实现前后端分离的Excel文件上传
-
后端springboot、mybatisplus,前端vue-cli3、elementUI、axios,使用阿里巴巴提供的easyExcel导入导出excel表格
-
前后端分离下载Excel文件
-
Springboot采用EasyPoi采用前后端分离快速实现Excel导出功能
-
前后端分离,Excel导出实现
-
SpringBoot+vue前后端分离实现下载导出Excel功能,下载Excel为undefined,null,乱码...等坑