題外話
- 本篇文章是之前文章的第二篇:有興趣的讀者可以看看 SpringBoot + Vue 如何實現導出Excel操作,這篇文章幫你解決!
1.所用框架
- 後端技術棧 Spring Boot
- 前端技術棧 Vue
2.後端接口實現
- 導入 POI 依賴
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
- 創建導入 Excel 接口
- 導入 Excel 操作我們可以分爲3個步驟:
- 首先獲取到用戶上傳的 Excel 文件
- 解析 Excel 文件,將 Excel 解析成數據庫所需要的數據
- 進行數據庫添加操作
- 後端接口如何設計,代碼如下:
/**
* 導入 Excel 數據
*
* @param file 你要導入的 Excel 文件
* @return
* @throws IOException
*/
@PostMapping("/import")
public RespBean importData(MultipartFile file) throws IOException {
// 1.自定義一個工具類拿到要解析的文件並解析成要存儲的數據
List<Employee> list = POIUtils.excel2Employee(file);
// 2.遍歷輸出你解析的數據格式是否正確
for (Employee employee : list) {
System.out.println(employee.toString());
}
// 3.進行數據庫添加操作
if (employeeService.addEmp(list) == 1) {
return RespBean.ok("上傳成功!");
}
return RespBean.error("上傳失敗!");
}
- 上文中出現的 RespBean 返回值是我項目中自定義的響應類,目的就是爲了告訴前端成功或者失敗而定義的一個工具類,代碼如下:
/**
* 響應結果類
*/
public class RespBean {
// 自定義狀態碼
private Integer status;
// 自定義響應消息內容
private String msg;
// 自定義返回的對象
private Object obj;
public static RespBean build() {
return new RespBean();
}
// 響應成功返回 200 正確消息 msg
public static RespBean ok(String msg) {
return new RespBean(200,msg,null);
}
// 相應成功返回 200 正確消息 msg 以及要返回的對象 obj
public static RespBean ok(String msg,Object obj) {
return new RespBean(200,msg,obj);
}
// 響應成功返回 500 錯誤消息 msg
public static RespBean error(String msg) {
return new RespBean(500,msg,null);
}
// 相應成功返回 500 錯誤消息 msg 以及要返回的對象 obj
public static RespBean error(String msg,Object obj) {
return new RespBean(500,msg,obj);
}
private RespBean() {
}
private RespBean(Integer status, String msg, Object obj) {
this.status = status;
this.msg = msg;
this.obj = obj;
}
public Integer getStatus() {
return status;
}
public RespBean setStatus(Integer status) {
this.status = status;
return this;
}
public String getMsg() {
return msg;
}
public RespBean setMsg(String msg) {
this.msg = msg;
return this;
}
public Object getObj() {
return obj;
}
public RespBean setObj(Object obj) {
this.obj = obj;
return this;
}
}
- POIUtils工具類方法代碼實現:
/**
* Excel 解析成數據集合
*
* @return
*/
public static List<Employee> excel2Employee(MultipartFile file) {
List<Employee> list = new ArrayList<>();
Employee employee = null;
try {
//1. 創建一個 workbook 對象
HSSFWorkbook workbook = new HSSFWorkbook(file.getInputStream());
//2. 獲取 workbook 中表單的數量
int numberOfSheets = workbook.getNumberOfSheets();
for (int i = 0; i < numberOfSheets; i++) {
//3. 獲取表單
HSSFSheet sheet = workbook.getSheetAt(i);
//4. 獲取表單中的行數
int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
for (int j = 0; j < physicalNumberOfRows; j++) {
//5. 跳過標題行
if (j == 0) {
continue;//跳過標題行
}
//6. 獲取行
HSSFRow row = sheet.getRow(j);
if (row == null) {
continue;//防止數據中間有空行
}
//7. 獲取列數
int physicalNumberOfCells = row.getPhysicalNumberOfCells();
employee = new Employee();
for (int k = 0; k < physicalNumberOfCells; k++) {
HSSFCell cell = row.getCell(k);
switch (cell.getCellType()) {
// 類型是 String 進入此 case 塊
case STRING:
String cellValue = cell.getStringCellValue();
switch (k) {
case 1:
employee.setName(cellValue);
break;
case 2:
employee.setWorkID(cellValue);
break;
case 3:
employee.setGender(cellValue);
break;
case 5:
employee.setIdCard(cellValue);
break;
case 6:
employee.setWedlock(cellValue);
break;
case 7:
employee.setNationId(cellValue);
break;
case 8:
employee.setNativePlace(cellValue);
break;
case 9:
employee.setPoliticId(cellValue);
break;
case 10:
employee.setPhone(cellValue);
break;
case 11:
employee.setAddress(cellValue);
break;
case 12:
employee.setDepartmentId(cellValue);
break;
case 13:
employee.setJobLevelId(cellValue);
break;
case 14:
employee.setPosId(cellValue);
break;
case 15:
employee.setEngageForm(cellValue);
break;
case 16:
employee.setTiptopDegree(cellValue);
break;
case 17:
employee.setSpecialty(cellValue);
break;
case 18:
employee.setSchool(cellValue);
break;
case 20:
employee.setWorkState(cellValue);
break;
case 21:
employee.setEmail(cellValue);
break;
}
break;
// 類型是 Date或者數字 進入此 case 塊
default: {
switch (k) {
case 4:
employee.setBirthday(cell.getDateCellValue());
break;
case 19:
employee.setBeginDate(cell.getDateCellValue());
break;
case 23:
employee.setBeginContract(cell.getDateCellValue());
break;
case 24:
employee.setEndContract(cell.getDateCellValue());
break;
case 22:
employee.setContractTerm(cell.getNumericCellValue());
break;
case 25:
employee.setConversionTime(cell.getDateCellValue());
break;
}
}
break;
}
}
// 最後將解析後的數據添加到員工集合中
list.add(employee);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
3.前端實現
- 前端使用的樣式是 Element-UI 中的 upload 上傳組件,頁面製作代碼如下:
1.:show-file-list
是否顯示已上傳文件列表
2.:before-upload
上傳文件前的調用事件
3.:on-success
上傳成功後的調用事件
4.:on-error
上傳成功後的調用事件
5.:disabled
是否禁用上傳組件
6.action
要上傳的路徑
<el-upload
:show-file-list="false"
:before-upload="beforeUpload"
:on-success="onSuccess"
:on-error="onError"
:disabled="importDisabled"
style="display: inline-flex;margin-right: 10px;"
action="這裏面填寫剛剛寫好的服務端接口路徑">
<el-button size="small" :disabled="importDisabled" type="success" :icon="importDataIcon">
{{importDataText}}
</el-button>
</el-upload>
- 數據定義,瞭解 Vue 的朋友們應該都知道這段代碼的含義,就是自定義幾個變量用來使用,這裏不過多解釋。大家不懂得可以去看 Vue 官網。
data(){
return{
// 導入按鈕的文本
importDataText: '導入數據',
// 導入按鈕的圖標
importDataIcon: 'el-icon-upload2',
// 導入按鈕是否被禁用
importDisabled: false
}
}
- 方法實現,代碼如下:
methods: {
// 導入文件失敗後回調
onError() {
this.importDataText = '導入數據';
this.importDataIcon = 'el-icon-upload2';
this.importDisabled = false;
this.initEmps();
this.$message.success("導入失敗!");
},
// 導入文件成功後回調
onSuccess() {
// 成功後文本修改爲原來的導入數據
this.importDataText = '導入數據';
// 圖標修改
this.importDataIcon = 'el-icon-upload2';
// 將上傳組件改爲允許使用
this.importDisabled = false;
// 調用刷新數據的方法
this.initEmps();
// message 彈出消息
this.$message.success("導入成功!");
},
// 上傳文件調用
beforeUpload() {
// 將文本修改爲正在導入
this.importDataText = '正在導入';
// 修改其圖標
this.importDataIcon = 'el-icon-loading';
// 將其上傳組件暫時禁用
this.importDisabled = true;
}
}
4.結果截圖
- 頁面中的上傳按鈕製作如圖:
- 選擇要上傳的 Excel 文件,大家可以自己作判斷上傳的文件是不是 Excel,由於我這裏沒有做判斷,大家可別學我,在真實的項目中還是要做的,前端做提升用戶體驗,後端做防止出錯。
- 正在導入中的按鈕也是不可以點擊的,這裏我們在事件中已經定義過了,圖標也顯示成正在加載的樣式,UI 界面還是非常不錯的。
- 導入成功的顯示導入成功,這裏我們可以去看下服務端接口打印的結果。
- 服務端打印的結果是正確的,這裏我們就完成了簡單的 Excel 導入功能。
5.結語
- 文中所用技術或許與你所用的技術不一樣,但是稍稍修改也是也可實現Excel導入功能的,這個其實沒有什麼技術點,代碼又不需要死記硬背,要用的時候拿過來用即可,如果各位看官有什麼問題,評論區留言或者私信我,我都會回覆你的。