SpringBoot - 使用HSSFWorkbook操作excel教程2(从excel文件导入数据)
作者:hangge | 2020-03-06 08:10
在之前的文章中演示了如何实现数据的导出,本文接着演示如何实现数据导入。对前端而言,数据导入就是文件上传,对后端这边则是获取上传的文件进行解析,并把解析出来的数据保存到数据库中。

(2)点击“导入数据”按钮选择 excel 文件后会自动上传:
(4)同时前端也会显示成功信息:
二、从 excel 文件导入数据
1,添加依赖
编辑项目的 pom.xml 文件,添加 poi 相关依赖:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
2,创建数据模型
这里我们定义一个 User 模型对象,后面将会把解析出来的数据转成这个数据模型集合。
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
private int id;
private String name;
private String gender;
private Date birthday;
private String workID;
}
3,创建导入工具类
为方便使用,这里封装一个用于导入数据的工具类。里面主要工作是获取上传文件的流,然后进行解析,最终将得到的数据集合返回。public class PoiUtils {
// 从excel文件中导入数据
public static List<User> importUser2List(MultipartFile file) {
List<User> users = new ArrayList<>();
try {
// 根据上传文件的流获取一个 HSSFWorkbook 对象
HSSFWorkbook workbook =
new HSSFWorkbook(new POIFSFileSystem(file.getInputStream()));
// 获取 workbook 中表单的个数
int numberOfSheets = workbook.getNumberOfSheets();
// 遍历表单
for (int i = 0; i < numberOfSheets; i++) {
HSSFSheet sheet = workbook.getSheetAt(i);
// 对于每个表单,先获取行数
int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
User user;
for (int j = 0; j < physicalNumberOfRows; j++) {
if (j == 0) {
continue;//标题行跳过
}
HSSFRow row = sheet.getRow(j);
if (row == null) {
continue;//没数据跳过
}
// 如果该行数据正常,则获取改行的单元格个数进行遍历
int physicalNumberOfCells = row.getPhysicalNumberOfCells();
user = new User();
for (int k = 0; k < physicalNumberOfCells; k++) {
HSSFCell cell = row.getCell(k);
switch (cell.getCellTypeEnum()) {
// 处理格式为普通文本的单元格数据
case STRING: {
String cellValue = cell.getStringCellValue();
if (cellValue == null) {
cellValue = "";
}
switch (k) {
case 1:
user.setName(cellValue);
break;
case 2:
user.setWorkID(cellValue);
break;
case 3:
user.setGender(cellValue);
break;
}
}
break;
// 处理其他格式的单元格数据
default: {
switch (k) {
case 0:
user.setId((int)cell.getNumericCellValue());
break;
case 4:
user.setBirthday(cell.getDateCellValue());
break;
}
}
break;
}
}
users.add(user);
}
}
} catch (IOException e) {
e.printStackTrace();
}
// 将遍历得到的数据集合返回
return users;
}
}
4,数据导入接口
我们创建一个 Controller 调用这个工具类来获取 excel 文件中的人员数据:@RestController
public class HelloController {
@PostMapping("/importUser")
public String importUser(MultipartFile file) {
List<User> users = PoiUtils.importUser2List(file);
System.out.println("--- 共有" + users.size() + "条数据 ---");
for (User user: users) {
System.out.println(user);
}
return "导出成功!";
}
}
5,前端实现
前端主要是一个 Excel 表格的上传,这里直接采用 Element 的文件上传控件,具体代码如下:
(1)el-upload 组件属性介绍:
- accept:表示接收的上传文件类型
- action:表示上传接口
- :on-success:表示上传成功时的回调
- :on-error:表示上传失败时的回调
- :disabled:表示当 fileUploadBtnText 属性的值为“正在导入”时禁用上传控件
- :before-upload:表示文件上传前的回调
(2)el-button 组件属性介绍:
- :loading="fileUploadBtnText=='正在导入'" 表示当 fileUploadBtnText 文本为“正在导入”时,显示一个 Loading 加载
<template>
<div>
<el-upload
:show-file-list="false"
accept="application/vnd.ms-excel"
action="/importUser"
:on-success="fileUploadSuccess"
:on-error="fileUploadError" :disabled="fileUploadBtnText=='正在导入'"
:before-upload="beforeFileUpload" style="display: inline">
<el-button size="mini" type="success" :loading="fileUploadBtnText=='正在导入'">
<i class="fa fa-lg fa-level-up" style="margin-right: 5px"></i>{{fileUploadBtnText}}
</el-button>
</el-upload>
</div>
</template>
<script>
export default{
data(){
return {
fileUploadBtnText: '导入数据', // 按钮文字
}
},
methods: {
// 文件上传成功的回调
fileUploadSuccess(response, file, fileList) {
if (response) {
this.$message({type: 'success', message: response});
}
this.fileUploadBtnText = '导入数据';
},
// 文件上传失败的回调
fileUploadError(err, file, fileList) {
this.$message({type: 'error', message: "导入失败!"});
this.fileUploadBtnText = '导入数据';
},
// 文件上传前的回调
beforeFileUpload(file) {
this.fileUploadBtnText = '正在导入';
}
}
}
</script>
<style>
</style>
6,运行测试
(1)准备一个用于上传的 excel 文件,内容如下:

(2)点击“导入数据”按钮选择 excel 文件后会自动上传:

(3)后端接收到文件后解析并打印出相关信息:
(4)同时前端也会显示成功信息:
全部评论(0)