業務:批量導入不同用戶的檔案信息,excel格式爲:信息用戶(獨一無二)- 姓名 - 性別 - …
數據庫檔案字段值表爲:信息用戶id-檔案字段id-檔案字段值
已有插入方法:add(String username, Integer[] fieldIds, String[] fieldValues),傳入信息用戶、檔案字段id、檔案字段值,其中信息用戶username將用來查詢得到數據庫中對應的信息用戶id進行操作;fieldIds與fieldValues按數組中的下標一一對應。
效果圖:
思路:
我是這樣想的,先把excel中的一行行數據返回成可以操作的形式。
首先聲明一個Map<String, Object> resultMap = new HashMap<>(),用於放入執行結果code以及數據rowList。
其中
code是代表執行結果,如文件值爲空/格式有誤情況;
rowList是excel返回成的一行一行的數據,即一個個字符串數組List<String[]> rowList = new ArrayList<>();
/**
* 將excel文件返回成Map
*
* @param file
* @return 返回Map<String, Object> key有兩種, ①code爲狀態碼;②rowList爲數據集合
*/
public static Map<String, Object> excelToMap(MultipartFile file) {
Map<String, Object> resultMap = new HashMap<>();
List<String[]> rowList = new ArrayList<>();
try {
String suffer = file.getOriginalFilename().substring(file.getOriginalFilename().indexOf(".") + 1);
if ("xls".equals(suffer) || "xlsx".equals(suffer)) {
InputStream in = file.getInputStream();
HSSFWorkbook workbook = new HSSFWorkbook(in);
// 得到sheet
HSSFSheet sheet = workbook.getSheetAt(0);
if (sheet != null) {
// 得到每行的值
// getLastCellNum比列標大1,行標&列標都以0開始。
int size = sheet.getRow(0).getLastCellNum();
for (int i = 0; i <= sheet.getLastRowNum(); i++) {
HSSFRow row = sheet.getRow(i);
String[] cellArr = new String[size];
// 得到一行每列的值
for (int j = 0; j < size; j++) {
HSSFCell cell = row.getCell(j);
if (cell == null || cell.getCellTypeEnum() == CellType.BLANK) {
cellArr[j] = new String(" ".getBytes("UTF-8"));
continue;
}
cell.setCellType(CellType.STRING);//單元格類型統一設置爲String,便於取出
String cellValueStr = new String(cell.getStringCellValue().getBytes("UTF-8"));
cellArr[j] = cellValueStr;
}
rowList.add(cellArr);
resultMap.put("rowList", rowList);
}
resultMap.put("code", 200);
return resultMap;
}
//文件值爲空
resultMap.put("code", 0);
return resultMap;
}
//文件格式有誤
resultMap.put("code", -1);
return resultMap;
} catch (Exception e) {
logger.info(e.toString());
//文件格式有誤
resultMap.put("code", -1);
return resultMap;
}
}
然後判斷執行結果code,如果成功則接着獲取rowList。
將rowList中的第一行即標題進行遍歷並在數據庫中查詢,得到其對應的檔案字段id,返回成Integer[] fieldIds;再將rowList中的其他行進行遍歷,得到 要插入的值 ,返回成String[] cellArr,其中cellArr[0]爲信息用戶username。並將cellArr數組裏其餘的值的編碼格式轉換成utf-8,返回成String[] fieldValues。
最後一行一行用前面說的add(String username, Integer[] fieldIds, String[] fieldValues)方法進行添加操作。
/**
* 批量導入信息數據
*/
@Transactional(propagation = Propagation.REQUIRED)
@PostMapping("/batchAdd")
@ResponseBody
public AjaxResult batchAdd(@RequestParam(value = "file", required = false) MultipartFile file) {
try {
Map<String, Object> excelToMap = ExcelUtils.excelToMap(file);//將excel轉成map
Integer code = (Integer) excelToMap.get("code");//自動拆箱與int比大小
if (code == 200) {
List<String[]> rowList = (List<String[]>) excelToMap.get("rowList");
//判斷第一個單元格值是否爲信息用戶
String firstCell = rowList.get(0)[0];
if (firstCell.equals("信息用戶")) {
List<String[]> rowList = (List<String[]>) excelToMap.get("rowList");
String[] firstRow = rowList.get(0);//獲取到第一行,即excel標題行
Integer[] fieldIds = new Integer[(firstRow.length - 1)];//將excel標題行的value遍歷,獲取數據庫中對應字段id
for (int i = 1; i < firstRow.length; i++) {
String cellValue = firstRow[i];
QueryWrapper<Field> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("field_name", cellValue);
Integer id = fieldService.list(queryWrapper).get(0).getId();
fieldIds[(i - 1)] = id;
}
//獲得username以及fieldValues
Integer resultCode;//導入後返回code
int sum = 0;//總需導入數
int successNum = 0;//成功導入數
//int quitNum = 0;//跳過導入數
int failNum = 0;//失敗導入數
for (int i = 1; i < rowList.size(); i++) {
String[] cellArr = rowList.get(i);
//判斷username是否爲空
String username = cellArr[0];
if (username.trim().length() != 0) {
sum = sum + 1;
String[] fieldValues = new String[(firstRow.length - 1)];
for (int j = 1; j < cellArr.length; j++) {
if (cellArr[j] == null) {
continue;
}
fieldValues[(j - 1)] = new String(encoder.encode(cellArr[j].getBytes("UTF-8")), StandardCharsets.UTF_8);//編碼轉換成utf-8
}
//獲得成功導入數以及跳過數
resultCode = add(username, fieldIds, fieldValues).getCode();
switch (resultCode) {
case 200:
successNum = successNum + 1;
break;
default:
failNum = failNum + 1;
}
} else continue;
}
String message = "總需導入用戶數:" + sum + "</br>導入成功用戶數:" + successNum + " </br>導入失敗用戶數:" + failNum + "。";
return success(message);
}
}
return error("導入文件有誤,請檢查文件格式!");
} catch (Exception e) {
logger.info(e.toString());
return error();
}
}
然後前端
<form class="form-horizontal m">
<div class="form-group">
<label class="col-sm-3 control-label ">Excel文件:</label>
<div class="col-sm-8">
<input class="" type="file" id="file" name="file"
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
/>
</div>
</div>
<button type="button" class="btn btn-primary" onclick="uploadFile()">提交</button>
</form>
function uploadFile() {
let formData = new FormData();
let file = $('#file')[0].files[0];
if (typeof (file) != "undefined") {
$.modal.msgLoading("處理中,請稍後...");
formData.append("file", file);
$.ajax({
cache: true,
type: "POST",
url: rootPath + "/xxxController/batchAdd",
data: formData,
processData: false,
contentType: false,
dataType: "json",
async: false,
error: function (request) {
$.modal.alertError("上傳文件有誤");
},
success: function (data) {
let content = data.message;
if (data.code == 200) {
layer.alert(content, {
icon: 1,
title: "系統提示",
btn: ["確認"],
btnclass: ["btn btn-primary"],
}, function () {
$.modal.close();
$.table.refresh(window.rootPath + "/UserController/list");
});
} else {
$.modal.alertError(data.message);
}
}
});
}
}
else {
$.modal.alertError("未上傳Excel文件");
}
}
消息彈出框用的是若依,
附上若依操作手冊:https://www.w3cschool.cn/ruoyi/ruoyi-8cnv311f.html