excel 文件下拉框字典项
要转换为数据库状态
fault_code为字符串类型
一般通过后端处理
写一个监听器类,处理从流中得到的数据
有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.wedu.modules.app.entity.UserEntity;
import com.wedu.modules.fault.entity.Register;
import com.wedu.modules.fault.mapper.RegisterMapper;
import com.wedu.modules.fault.service.IRegisterService;
import com.wedu.modules.sys.entity.SysDictEntity;
import com.wedu.modules.sys.entity.SysUserEntity;
import com.wedu.modules.sys.service.SysDictService;
import com.wedu.modules.sys.service.SysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import static com.wedu.modules.fault.util.TimeConversionStringUtil.*;
import static com.wedu.common.utils.ShiroUtils.getUserId;
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class UploadDataListener extends AnalysisEventListener<Register> {
private static final Logger LOGGER = LoggerFactory.getLogger(UploadDataListener.class);
/**
* 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 5;
List<Register> list = new ArrayList<>();
/**
* 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
*/
private IRegisterService registerService;
private SysUserService userService;
private SysDictService dictService;
// public UploadDataListener() {
// // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
// demoDAO = new DemoDAO();
// }
/**
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
*
* @param registerService
*/
public UploadDataListener(IRegisterService registerService,SysUserService userService, SysDictService dictService) {
this.registerService = registerService;
this.userService = userService;
this.dictService = dictService;
}
/**
* 这个每一条数据解析都会来调用
*
* @param data
* one row value. Is is same as {@link }
* @param context
*/
@Override
public void invoke(Register data, AnalysisContext context) {
LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
list.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
list.clear();
}
}
/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
LOGGER.info("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
LOGGER.info("{}条数据,开始存储数据库!", list.size());
// List<SysUserEntity> userEntityList = new ArrayList<>();
// 获取字典字符列表
List<SysDictEntity> dictEntities = dictService.maintenanceList("faultCode");
for (Register register : list) {
//处理时间字符串为时间戳
long redTime = convertToMilliseconds(register.getRedTimeChar());
register.setRedTime(redTime);
long repTime = convertToMilliseconds(register.getRepTimeChar());
register.setRepTime(repTime);
register.setCreateTime(new Date());
register.setCreateBy(getUserId());
// 遍历字典和实体类进行比对然后重新赋值
for (SysDictEntity dictEntity : dictEntities) {
if (dictEntity.getName().equals(register.getFaultCode())) {
register.setFaultCode(dictEntity.getValue());
}
}
// 为了关联表的插入,模拟实现插入用户
// // 检查用户名是否已存在
// boolean usernameExists = userService.checkUsernameExists(register.getSysUsername());
//
// if (!usernameExists) {
// SysUserEntity user = new SysUserEntity();
// // 取出user表必要信息,设置信息必要的属性
// user.setUsername(register.getSysUsername());
// user.setMobile(register.getPhone());
// user.setPassword("123");
// user.setStatus(1);
// user.setCreateUserId(getUserId());
// userService.saveUser(user);
userEntityList.add(user);
// }
}
// 执行sql
// 执行用户信息批量插入
// if (!userEntityList.isEmpty()) {
// userService.saveBatch(userEntityList);
// }
registerService.saveBatch(list);
LOGGER.info("存储数据库成功!");
}
}
controller层访问接口
/**
* easy excel上传
* @param file
* @return
* @throws Exception
*/
@PostMapping("/importEasyExcel")
public R importEasyExcel(MultipartFile file) throws Exception {
// 测试获取数据
// String fileName = "C:\\Users\\HP\\Desktop\\ey导出.xlsx";
// List<Register> list = EasyExcel.read(fileName).head(Register.class).sheet().doReadSync();
// for (Register data : list) {
// System.out.println("读取到数据:{}" + JSON.toJSONString(data));
// }
EasyExcel.read(file.getInputStream(), Register.class, new UploadDataListener(registerService, userService, dictService)).sheet().doRead();
return R.ok();
}
前端:使用element组件的上传方法
使用异步Ajax方法
按钮绑定方法
<el-form-item>
<el-upload
class="upload-demo"
action="#"
:on-change="handleChange"
:on-exceed="handleExceed"
:file-list="fileList"
:limit="1"
multiple
:auto-upload="true"
>
<el-button
size="small"
round
type="primary"
>点击上传</el-button>
</el-upload>
</el-form-item>
methods方法
// 导入excel
// 文件超出个数提示
handleExceed (files, fileList) {
this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
},
handleChange (file) {
let formData = new FormData()
formData.append('file', file.raw) // 传文件
this.$http({
url: this.$http.adornUrl('/register/importEasyExcel'),
method: 'post',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500
})
this.getDataList()
this.$refs.upload.clearFiles() // 清除文件
} else {
this.$message.error(data.msg)
}
})
},