wg-basic-doc/docs/code-template/excel-upload.md
2022-05-25 18:33:19 +08:00

284 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# EasyExcel 上传(导入)
以人口Population导入为例
1. 包含 **Excel实体类**、**错误实体类**、**导入监听器**,其中 **错误实体类** 非必须。
2. 如果不需要返回错误,可忽略输出错误文件的代码。
## Excel实体类
```java
import com.alibaba.excel.annotation.ExcelProperty;
public class PopulationExcel {
@ExcelProperty(index = 0)
private String name;
@ExcelProperty(index = 1)
private String idCard;
@ExcelProperty(index = 2)
private String areaCode;
@ExcelProperty(index = 3)
private String homeAddress;
// get set
}
```
## 错误试题类
```java
import com.alibaba.excel.annotation.ExcelProperty;
public class PopulationExcelError {
@ExcelProperty(index = 0)
private String name;
@ExcelProperty(index = 1)
private String idCard;
@ExcelProperty(index = 2)
private String areaCode;
@ExcelProperty(index = 3)
private String homeAddress;
@ExcelProperty(index = 4)
private String reason;
// get set
}
```
## 监听器
```java
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;
public abstract class PopulationExcelListener extends AnalysisEventListener<PopulationExcel> {
private static final Integer MAX_READ_COUNT = 100;
private List<PopulationExcel> populationExcels = new ArrayList<>();
@Override
public void invoke(PopulationExcel populationExcel, AnalysisContext analysisContext) {
if (populationExcels.size() > MAX_READ_COUNT) {
// 超过读取最大量,执行保存,
handle(populationExcels);
populationExcels.clear();
} else {
// 未达到读取最大量,继续读取
populationExcels.add(populationExcel);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
handle(populationExcels);
populationExcels.clear();
}
/**
* 处理
*
* @param rows
*/
public abstract void handle(List<PopulationExcel> rows);
}
```
## 导入代码
### controller 层
```java
@ApiOperation(value = "试题Excel", notes = "试题Excel接口")
@ApiImplicitParams({
@ApiImplicitParam(name = "excel", value = "文件名称", paramType = "form"),
})
@ApiResponses({@ApiResponse(code = 400, message = "请求失败", response = ErrorResult.class)})
@PostMapping("import-excel")
public UploadExcelResultDTO importExcel(MultipartFile excel) throws IOException {
if (Objects.isNull(excel)) {
throw new ParamsException("Excel不能为空");
}
// 判断后缀
if (!excel.getOriginalFilename().endsWith(IFileConstant.EXCEL_SUFFIX_XLS)
&& !excel.getOriginalFilename().endsWith(IFileConstant.EXCEL_SUFFIX_XLSX)) {
throw new ParamsException("文件格式为Excel");
}
return populationService.importExcel(excel);
}
```
### service 层
```java
@Override
public UploadExcelResultDTO importExcel(MultipartFile excel) throws IOException {
// 要输出的错误内容
List<PopulationExcelError> populationExcelErrors = new ArrayList<>();
long startTime = System.currentTimeMillis();
// 读取 Excel
EasyExcel.read(excel.getInputStream(), PopulationExcel.class, new PopulationExcelListener() {
@Override
public void handle(List<PopulationExcel> populationExcels) {
// 这里处理数据,一般是入库
}
}).headRowNumber(2).sheet().doRead();
long endTime = System.currentTimeMillis();
// 生成的错误文件ID下载时使用
String excelFileId = null;
if (populationExcelErrors.size() > 0) {
excelFileId = new AbstractErrorExcelHandler<PopulationExcelError>(fileService) {
@Override
public List<List<String>> excelHeaderNames() {
// 构建错误 Excel 标题,与错误类对应
return simpleExcelHeader(new String[]{"序号", "姓名", "身份证", "错误原因"});
}
}.saveErrorExcel(populationExcelErrors);
}
// 返回实体类,
return new UploadExcelResultDTO(populationExcelErrors.size(), endTime - startTime, excelFileId);
}
```
## 模板下载接口
```java
@GetMapping("upload/upload-excel-template")
public void excelTemplate(HttpServletResponse response) throws IOException {
InputStream inputStream = PopulationRouteController.class.getClassLoader().getResourceAsStream("templates/population/upload/upload-excel-template.xls");
RequestUtil.download(response, inputStream, "人口导入模板.xls");
}
```
## 列表导入按钮
```html
<button type="button" class="layui-btn layui-btn-sm" id="uploadExcel">
<i class="fa fa-lg fa-cloud-upload"></i> 导入数据
</button>
```
## 列表导入事件
```javascript
$(document).on('click', '#uploadExcel', function() {
top.dialog.open({
url: top.restAjax.path('route/population/upload/upload-excel', []),
title: '导入人口数据',
width: '300px',
height: '196px',
onClose: function() {
reloadTable();
}
});
});
```
## 导入页面代码
```html
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<base th:href="${#request.getContextPath() + '/'}">
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="assets/fonts/font-awesome/css/font-awesome.css"/>
<link rel="stylesheet" href="assets/layuiadmin/layui/css/layui.css" media="all">
<link rel="stylesheet" href="assets/layuiadmin/style/admin.css" media="all">
</head>
<body>
<div class="layui-anim layui-anim-fadein">
<div class="layui-card" style="text-align: center;">
<div class="layui-card-body" style="padding: 15px;">
<blockquote class="layui-elem-quote">下载“下载模板”整理数据点击“导入数据”上传格式为xls或xlsx</blockquote>
<button id="downloadFile" type="button" class="layui-btn layui-btn" onclick="window.open('route/population/upload/upload-excel-template', 'downloadTarget')">
<i class="fa fa-lg fa-cloud-download"></i> 下载模板
</button>
<button type="button" class="layui-btn layui-btn" id="uploadExcel">
<i class="fa fa-lg fa-cloud-upload"></i> 导入数据
</button>
</div>
</div>
<iframe style="display: none" name="downloadTarget"></iframe>
</div>
<script src="assets/layuiadmin/layui/layui.js"></script>
<script>
layui.config({
base: 'assets/layuiadmin/' //静态资源所在路径
}).extend({
index: 'lib/index' //主入口模块
}).use(['index', 'upload', 'common'], function(){
var $ = layui.$;
var form = layui.form;
var common = layui.common;
function closeBox() {
parent.layer.close(parent.layer.getFrameIndex(window.name));
}
// 初始化Excel上传
function initExcelUpload() {
// Excel上传
var uploadLoading;
layui.upload.render({
elem: '#uploadExcel',
url: 'api/population/import-excel',
accept: 'file',
exts: 'xls|xlsx',
field: 'excel',
before: function() {
uploadLoading = layer.msg('正在上传,请稍后...', {icon: 16, time: 0, shade: 0.3});
},
done: function(data) {
layer.close(uploadLoading);
if(data.failedCount > 0) {
layer.open({
type: 1,
title: false,
closeBtn: 0,
shadeClose: true,
skin: '',
content: '<div style="padding: 15px;">' +
'<div>失败数量:'+ data.failedCount +'</div><br/>' +
'<div><a class="error-excel" href="javascript:void(0);" onclick="window.open(\'route/file/download/false/'+ data.errorExcel +'\');" target="downloadTarget">点击下载错误信息</a></div>' +
'</div>'
});
} else {
layer.msg('导入成功', {time: 2000}, function() {
closeBox();
});
}
},
error: function(data, index){
layer.close(uploadLoading);
if(data != null) {
top.dialog.msg(data.msg);
}
},
});
}
initExcelUpload();
$('.close').on('click', function() {
closeBox();
});
});
</script>
</body>
</html>
```