1、数据导入:减轻录入工作量
2、数据导出:统计信息归档
3、数据传输:异构系统之间数据传输
EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。
文档地址:https://alibaba-easyexcel.github.io/index.html
github地址:https://github.com/alibaba/easyexcel
<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
@ExcelProperty(value = "学生id")
private Integer id;
@ExcelProperty(value = "学生姓名")
private String name;
@ExcelProperty(value = "学生年龄")
private Integer age;
}
public class WriteExcel {
public static void main(String[] args) {
//准备文件路径
String fileName="D:/destory/test/easyexcel.xls";
//写出文件
EasyExcel.write(fileName, Student.class).sheet("easyexcel")
.doWrite(data());
}
private static List<Student> data(){
ArrayList<Student> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Student student = new Student(i, "董德" + 1, 22 + i);
list.add(student);
}
return list;
}
}
给实体的每一个属性加上索引,对应xls表里面的具体列
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
@ExcelProperty(value = "学生id",index = 0)
private Integer id;
@ExcelProperty(value = "学生姓名",index = 1)
private String name;
@ExcelProperty(value = "学生年龄",index = 2)
private Integer age;
}
public class EasyExcelLinster extends AnalysisEventListener<Student> {
List<Student> list= new ArrayList<Student>();
//一行一行的去读取里面的数据
@Override
public void invoke(Student student, AnalysisContext analysisContext) {
System.out.println(student);
list.add(student);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
public class ReadExcel {
public static void main(String[] args) {
//准备文件路径
String fileName="D:/destory/test/easyexcel.xls";
EasyExcel.read(fileName, Student.class, new ExcelListener()).sheet().doRead();
}
}
文件的导入导出也就意味着是文件的下载和批量上传功能,
导出:需要将数据库里面的文件以附件的形式下载到本地电脑,需要参数为respoonse对象,返回值类型为void
controller相关操作,将逻辑交由service去做
@ApiOperation("导出")
@GetMapping("/exportData")
public void exportData(HttpServletResponse response){
dictService.exportData(response);
}
service
@Override
public void exportData(HttpServletResponse response) {
try {
//设置相关参数
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("数据字典", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");
//获取文件
List<Dict> list = this.baseMapper.selectList(null);
//转换文件
ArrayList<DictEeVo> dictEeVos = new ArrayList<>();
for (Dict dict : list) {
DictEeVo dictEeVo = new DictEeVo();
//转换
BeanUtils.copyProperties(dict, dictEeVo);
//添加
dictEeVos.add(dictEeVo);
}
//写出
EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("数据字典").doWrite(dictEeVos);
} catch (Exception e) {
e.printStackTrace();
}
}
window.open("http://localhost:8202/admin/cmn/dict/exportData")
里面写实际的url地址
前端的操作,非常简单,只需要我们添加单击按钮以及在事件里面操作即可
<div class="el-toolbar">
<div class="el-toolbar-body" style="justify-content: flex-start;">
<el-button type="text" @click="exportData"><i class="fa fa-plus"/> 导出</el-button>
</div>
</div>
exportData() {
window.open("http://localhost:8202/admin/cmn/dict/exportData")
},
导入:需要将本地文件插入到数据库,参数:multiparefile,返回值:"成功or失败"
使用excel进行导入需要监听器的配合,使用监听器对读取的文件进行操作
监听器:用来读取文件,并将数据插入数据库
@Component
public class DictHandler extends AnalysisEventListener<DictEeVo> {
@Autowired
private DictMapper dictMapper;
//一行一行的读取excel里面的内容
@Override
public void invoke(DictEeVo dictEeVo, AnalysisContext analysisContext) {
//转换对象
Dict dict = new Dict();
BeanUtils.copyProperties(dictEeVo,dict);
//设置默认逻辑删除值
dict.setIsDeleted(0);
//写入数据库
dictMapper.insert(dict);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
controller读取文件
@ApiOperation("导入")
@PostMapping("/importData")
public R importData(MultipartFile file){
//读取文件
try {
EasyExcel.read(file.getInputStream(), DictEeVo.class, dictHandler).sheet().doRead();
return R.ok().message("导入成功");
} catch (IOException e) {
e.printStackTrace();
return R.error().message("导入失败");
}
}
结合swanger测试发现文件可以成功导入到数据库,开始前端的开发
加入按钮以及上传的弹框
<div class="app-container">
<!-- 上传与下载的按钮 -->
<div class="el-toolbar">
<div class="el-toolbar-body" style="justify-content: flex-start;">
<el-button type="text" @click="exportData"><i class="fa fa-plus"/> 导出</el-button>
<el-button type="text" @click="importData"><i class="fa fa-plus"/> 导入</el-button>
</div>
<!-- 上传文件的弹框 -->
<el-dialog title="导入" :visible.sync="dialogImportVisible" width="480px">
<el-form label-position="right" label-width="170px">
<el-form-item label="文件">
<el-upload
:multiple="false"
:on-success="onUploadSuccess"
:action="base_url"
class="upload-demo">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传xls文件,且不超过500kb</div>
</el-upload>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogImportVisible = false">取消</el-button>
</div>
</el-dialog>
点击上传按钮事件以及上传成功事件
//导入文件
importData(){
this.dialogImportVisible=true
},
onUploadSuccess(response, file, fileList){
//debugger
if(response.success){
//成功
this.$message.success(response.message);
//弹框消失
this.dialogImportVisible=false
//刷新列表
this.getAllDict(1)
}