SpringBoot中Excel表的导入、导出功能的实现
文章目录
- 一、easyExcel简介
- 二、Excel表的导出
- 2.1 添加 Maven 依赖
- 2.2 创建导出数据的实体类
- 4. 编写导出接口
- 5. 前端代码
- 6. 实现效果
- 三、excel表的导出
- 1. Excel表导入的整体流程
- 1.1 配置文件存储路径
- 2. 前端实现
- 2.1 文件上传组件
- 2.2 文件上传逻辑
- 3. 后端实现
- 3.1 文件上传接口
- 3.2 数据解析接口
- 4. 实现效果
一、easyExcel简介
Excel表的导入导出有很多种方式,这里我们使用easyExel。EasyExcel 是阿里巴巴推出的一个处理 Excel 文件的库,特别适合大数据量的 Excel 文件操作,具有性能优越、内存占用小等特点。
二、Excel表的导出
集成 EasyExcel 到 Spring Boot 项目:
2.1 添加 Maven 依赖
首先,在 pom.xml
中添加 EasyExcel 的依赖:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.6</version> <!-- 版本号可以根据需要调整 -->
</dependency>
2.2 创建导出数据的实体类
根据需要创建实体类,使用@ExcelProperty
注解标注实体类的字段,指定表头名称和列索引,EasyExcel 会根据这个类的字段和注解来生成 Excel 文件。
@Data
public class PersonVO {
@ExcelProperty(value = "人员ID", index = 0)
private Integer personId;
@ExcelIgnore
private Integer communityId;
@ExcelProperty(value = "单元名称", index = 2)
private String termName;
@ExcelProperty(value = "房号", index = 3)
private String houseNo;
@ExcelProperty(value = "姓名", index = 4)
private String userName;
@ExcelProperty(value = "性别", index = 5)
private String sex;
@ExcelProperty(value = "手机号", index = 6)
private String mobile;
@ExcelIgnore
private String faceUrl;
@ExcelProperty(value = "居住性质", index = 7)
private String personType;
@ExcelIgnore
private Integer state;
@ExcelIgnore
private String creater;
@ExcelIgnore
private Date createTime;
@ExcelProperty(value = "备注", index = 8)
private String remark;
@ExcelProperty(value = "社区名称", index = 1)
private String communityName;
}
不需要导出的列使用
@ExcelIgnore
忽略
4. 编写导出接口
@RestController
public class ExcelController {
@GetMapping("/exportExcel")
public Result exportExcel(PersonListForm personListForm){
//查询数据
PageVO pageVO = this.personService.personList(personListForm);
List<PersonVO> list = pageVO.getList();
// 设置文件路径和文件名
String path = "D:/community/excel_export/";
String fileName = path + "personInfo_" + System.currentTimeMillis() + ".xlsx";
// 使用 EasyExcel 导出数据
EasyExcel.write(fileName, PersonVO.class)
.sheet("人员信息")
.doWrite(list); // 直接写入数据
return Result.ok().put("data", fileName);
}
}
5. 前端代码
//导出按钮
<el-form-item>
<el-button type="primary" icon="el-icon-download" @click="handleExcel">导出</el-button>
</el-form-item>
handleExcel() {
this.$confirm('是否确认导出所有数据项?').then(() => {
exportExcel(this.listQuery).then(res => {
const fileUrl = process.env.VUE_APP_BASE_API + '/sys/person/exportExcel?fileName=' + res.data;
const link = document.createElement('a');
link.href = fileUrl;
link.download = res.data; // 下载文件的名称
link.click();
});
}).catch(() => {});
}
6. 实现效果
三、excel表的导出
1. Excel表导入的整体流程
前端部分:
- 用户通过上传组件选择Excel文件。
- 文件上传到后端服务器。
- 后端返回文件路径或标识符。
- 前端调用解析接口,将文件路径传递给后端。
- 后端解析Excel文件,将数据保存到数据库。
- 返回解析结果给前端,提示用户成功或失败信息。
后端部分:
- 提供文件上传接口,接收Excel文件并保存到服务器。
- 提供解析接口,读取Excel文件内容并处理数据。
- 将解析的数据保存到数据库。
- 返回解析结果。
1.1 配置文件存储路径
确保文件存储路径是动态配置的,避免硬编码。可以在application.yml
中配置文件存储路径:
upload:
excel: D:/community/upload/excel/
在代码中读取配置:
@Value("${upload.excel}")
private String excel;
2. 前端实现
2.1 文件上传组件
使用Element UI的el-upload
组件实现文件上传功能。
<template>
<el-dialog
:title="'上传住户资料'"
:close-on-click-modal="false"
:visible.sync="visible"
width="60%"
>
<el-form label-width="100px" style="width:95%;" @keyup.enter.native="dataFormSubmit()">
<el-row>
<el-col :span="24">
<el-form-item label="导入住户资料">
<el-upload
class="avatar-uploader"
:headers="headers"
:action="uploadUrl"
:show-file-list="false"
:on-success="handleAvatarSuccess"
name="uploadExcel"
:before-upload="beforeAvatarUpload">
<i class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="模板下载">
<a :href="process.env.VUE_APP_BASE_API + '/community/upload/excel/personInfo.xls'" download>点击下载Excel模板</a>
</el-form-item>
</el-col>
<el-col :span="24">
<span style="color:red" v-html="errorInfo" />
</el-col>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dataFormSubmit()">确 定</el-button>
</span>
</el-dialog>
</template>
2.2 文件上传逻辑
在beforeAvatarUpload方法中,限制文件类型和大小
beforeAvatarUpload(file) {
this.errorInfo = '';
const ext = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase();
const imgSize = file.size / 1024 / 1024 < 10;
if (!['xls', 'xlsx'].includes(ext)) {
this.$message.error('文件格式只能为xls或xlsx文件');
return false;
}
if (!imgSize) {
this.$message.error('文件大小不能超过10MB');
return false;
}
return true;
}
在handleAvatarSuccess方法中,处理上传成功后的逻辑:
handleAvatarSuccess(response, file) {
if (response && response.code === 200) {
parsefile(response.data).then(res => {
if (res && res.code === 200) {
if (res.status === 'success') {
this.errorInfo = res.data;
this.$message.success('上传成功');
} else {
this.errorInfo = res.data;
this.$message.error('上传失败');
}
} else {
this.errorInfo = '解析文件失败';
this.$message.error('解析文件失败');
}
}).catch(error => {
console.error('解析文件失败', error);
this.errorInfo = '解析文件失败';
this.$message.error('解析文件失败');
});
} else {
this.errorInfo = '文件上传失败';
this.$message.error('文件上传失败');
}
}
3. 后端实现
3.1 文件上传接口
接收上传的Excel文件,并保存到服务器的临时目录中:
@PostMapping("/excelUpload")
public Result excelUpload(@RequestParam("uploadExcel") MultipartFile file) throws Exception {
if (file.getOriginalFilename().equals("")) {
return Result.error("没有选中要上传的文件");
} else {
String picName = UUID.randomUUID().toString();
String oriName = file.getOriginalFilename();
String extName = oriName.substring(oriName.lastIndexOf("."));
String newFileName = picName + extName;
File targetFile = new File(excel, newFileName);
// 保存文件
file.transferTo(targetFile);
return Result.ok().put("data", newFileName);
}
}
3.2 数据解析接口
读取Excel文件内容,解析数据并保存到数据库:
@LogAnnotation("导入数据")
@PostMapping("/parsefile/{fileName}")
public Result parsefile(@PathVariable("fileName") String fileName, HttpSession session) {
User user = (User) session.getAttribute("user");
try {
String basePath = excel + fileName;
List<ExcelVo> dataList = EasyExcel.read(new File(basePath), ExcelVo.class).sheet().doReadSync();
for (ExcelVo vo : dataList) {
Person single = new Person();
single.setPersonId(0);
single.setState(1);
single.setFaceUrl("");
single.setCommunityId(vo.getCommunityId());
single.setTermName(vo.getTermName());
single.setHouseNo(vo.getHouseNo());
single.setUserName(vo.getUserName());
single.setSex(vo.getSex());
single.setMobile(vo.getMobile());
single.setPersonType(vo.getPersonType());
single.setRemark(vo.getRemark());
single.setCreater(user.getUsername());
this.personService.save(single);
}
return Result.ok().put("status", "success").put("data", "数据导入完成!");
} catch (Exception e) {
e.printStackTrace();
return Result.error().put("status", "fail").put("data", "解析文件失败:" + e.getMessage());
}
}
4. 实现效果