1、添加依赖:

        <!-- 现在已经更新到1.1.2-beta5 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>1.1.1</version>
</dependency>

导入:

2、添加监听:

package com.aikucun.goods.biz.easyexcel;

import com.aikucun.goods.dao.model.vo.SkuModel;
import com.aikucun.goods.dao.model.vo.SkuUploadFailModel;
import com.aikucun.sc.common.utils.BeanUtils;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils; import java.util.List; public class SkuUploadListener extends AnalysisEventListener { private List<SkuUploadFailModel> uploadFailList = Lists.newArrayList(); private List<SkuModel> skuModelList = Lists.newArrayList(); private int totalSize = 0; /**
* 每解析一行,执行一次该方法
*/
@Override
public void invoke(Object object, AnalysisContext context) {
totalSize++;
SkuModel skuModel = (SkuModel) object;
if (!checkData(skuModel)) {
return;
}
skuModelList.add(skuModel);
} @Override
public void doAfterAllAnalysed(AnalysisContext context) { } private boolean checkData(SkuModel skuModel) { // 失败原因
String failMessage = "";
// itemCode
String itemCode = skuModel.getItemCode(); if (null == skuModel) {
failMessage = "数据为空";
}
// 验证sku
if (StringUtils.isEmpty(itemCode)) {
failMessage = "itemCode为空!";
} else {
if (skuModelList.contains(itemCode)) {
failMessage = failMessage + "itemCode重复!";
}
}
//品牌名称
if (StringUtils.isEmpty(skuModel.getBrandName())) {
failMessage = failMessage + "品牌名称为空!";
}
//条码必填
if (StringUtils.isEmpty(skuModel.getBarCode())) {
failMessage = failMessage + "条码为空!";
} if (StringUtils.isNotEmpty(failMessage)) {
SkuUploadFailModel failModel = new SkuUploadFailModel();
//数量校验???
BeanUtils.convert(skuModel, failModel);
failModel.setFailMessage(failMessage); uploadFailList.add(failModel);
return false;
}
return true; } public List<SkuUploadFailModel> getUploadFailList(){
return uploadFailList;
} public List<SkuModel> getSkuModelList(){
return skuModelList;
} public int getTotalSize() {
return totalSize;
}
}

3、导入商品controller:

    @PostMapping("/import-sku-list-async")
@ApiOperation("批量导入商品(异步)")
public Result importSkuListAsync(@RequestBody MultipartFile file) {
return skuService.importSkuListAsync(file);
}

4、ServiceImpl

@Override
public Result importSkuListAsync(MultipartFile file) { //1.参数校验
if (file == null || file.isEmpty()) {
throw new GoodsException("导入文件为空");
}
// 判断文件格式
String filename = file.getOriginalFilename();
String suffixName = filename.substring(filename.indexOf("."));
if (!".xlsx".equalsIgnoreCase(suffixName) && !".xls".equalsIgnoreCase(suffixName)) {
throw new GoodsException("文件格式要求:.xlsx/.xls");
}
dealDataAsync(file, suffixName);
return Result.success();
} /**
* 异步处理excel数据校验、落库、上传文件服务器等
*
* @param file
*/
@Async
public void dealDataAsync(MultipartFile file, String suffixName) { InputStream inputStream = null;
try {
inputStream = file.getInputStream();
} catch (Exception e) {
e.printStackTrace();
}
//1.注册任务
String dataFlag = System.currentTimeMillis() + "";
// 任务注册
Long id = reg("{\"service\":\"goods-web\"}", getUserName(), dataFlag, getRealName(), DataFileTaskTypeEnum.IMPORT.getType());
if (id == null) {
log.error("【导入商品】 uploadSkuFile 数据版本号:" + dataFlag + ", 注册导入任务失败");
return;
}
//2.excel数据校验
SkuUploadListener listener = new SkuUploadListener();
dealExcel(listener, suffixName, id, dataFlag, inputStream); //3.把错误数据分装集合中,正确数据封装集合中
// 验证失败的数据
List<SkuUploadFailModel> uploadFailList = listener.getUploadFailList();
// 验证通过的数据
List<SkuModel> skuModeList = listener.getSkuModelList();
// 总数量
int totalSize = listener.getTotalSize();
//4.把成功集合插入数据库,错误数据上传文件服务器
try {
for (SkuModel skuModel : skuModeList) {
Sku sku = new Sku();
BeanUtils.copyProperties(skuModel, sku);
saveOrUpdateSku(sku);
}
}catch (Exception e){
log.error("【导入商品】 数据版本号:{},保存采购单报错:{},错误详情:{}", dataFlag, e.getMessage(), e);
finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", totalSize, 0, "保存到数据库报错", dataFlag);
return;
}
//5.完成任务(上传失败数据到文件服务器)
// 导入状态
int status = DataFileTaskStatusEnum.SUCCESS.getType();
String fileUrl = "";
// 导入失败的数据,生成异常文件
if (!CollectionUtils.isEmpty(uploadFailList)) {
if (CollectionUtils.isEmpty(skuModeList)) {
status = DataFileTaskStatusEnum.FAIL.getType();
} else {
status = DataFileTaskStatusEnum.PART_SUCCESS.getType();
}
fileUrl = createErrFile(uploadFailList, dataFlag);
}
finish(id, status, fileUrl, totalSize, skuModeList.size(), "导入结束", dataFlag);
} private void dealExcel(SkuUploadListener listener, String suffixName, Long id, String dataFlag, InputStream file) {
ExcelTypeEnum excelTypeEnum;
if (ExcelTypeEnum.XLSX.getValue().equalsIgnoreCase(suffixName)) {
excelTypeEnum = ExcelTypeEnum.XLSX;
} else if (ExcelTypeEnum.XLS.getValue().equalsIgnoreCase(suffixName)) {
excelTypeEnum = ExcelTypeEnum.XLS;
} else {
log.error("【导入采购单】 uploadPurchaseFile 数据版本号:" + dataFlag + ",上传文件格式不是 " + ExcelTypeEnum.XLSX.getValue() + "/" + ExcelTypeEnum.XLS.getValue());
finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", 0, 0, "文件格式不正确", dataFlag);
return;
}
// 解析文件
try {
ExcelReader excelReader = new ExcelReader(file, excelTypeEnum, null, listener);
excelReader.read(new Sheet(1, 1, SkuModel.class));
} catch (Exception e) {
log.error("【导入采购单】 uploadPurchaseFile 数据版本号:{},解析文件报错:{},错误详情:{}", dataFlag, e.getMessage(), e);
finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", 0, 0, "解析文件报错", dataFlag);
return;
}
} /**
* 导入商品,异常文件生成
*
* @param modelList
* @param dataFlag
*/
private String createErrFile(List<SkuUploadFailModel> modelList, String dataFlag) {
// 生成文件类型
ByteArrayOutputStream out = null;
String fileUrl = "";
try {
out = new ByteArrayOutputStream();
ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
if (modelList.size() > FILE_SIZE) {
List<List<SkuUploadFailModel>> splitList = Lists.partition(modelList, FILE_SIZE);
for (int i = 0; i < splitList.size(); i++) {
//写一个sheet,
Sheet sheet = new Sheet(i + 1, 0, SkuUploadFailModel.class);
writer.write(splitList.get(i), sheet);
}
} else {
//写一个sheet,
Sheet sheet = new Sheet(1, 0, SkuUploadFailModel.class);
writer.write(modelList, sheet);
}
writer.finish();
CloudStorageService oss = oSSFactory.build();
String path = oss.getDefaultPath("/导入商品异常反馈.xlsx");
fileUrl = oss.upload((out).toByteArray(), path);
log.info("【导入商品】 createErrFile 数据版本号:" + dataFlag + ",生成文件url:" + fileUrl);
} catch (Exception e) {
log.error("【导入商品】 createErrFile 数据版本号:" + dataFlag + ",导出报错: " + e.getMessage(), e);
} finally {
try {
if (out != null) {
out.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return fileUrl;
} private Long reg(String param, String userName, String dataFlag, String realName, Integer type) { DataFileTaskDTO dataFileTaskDTO = new DataFileTaskDTO();
dataFileTaskDTO.setParams(param);
dataFileTaskDTO.setDataType(SystemModuleEnum.DOWNLOAD_GOODS.getType());
dataFileTaskDTO.setType(type);
dataFileTaskDTO.setRemark(SystemModuleEnum.DOWNLOAD_GOODS.getTypeName() + ",数据版本号:" + dataFlag);
dataFileTaskDTO.setSource(SystemModuleEnum.DOWNLOAD_GOODS.getSystem());
dataFileTaskDTO.setCreateUser(realName);
dataFileTaskDTO.setCreateUserJobNumber(userName); log.info("【导入商品】推送到磐石注册任务参数,dataFileTaskDTO:{}", JSONObject.toJSONString(dataFileTaskDTO));
Result ret = remote.reg(dataFileTaskDTO);
log.info("【导入商品】推送到磐石注册任务返回结果,ret:{}", JSONObject.toJSONString(ret));
if (!CheckUtils.isNull(ret) && ret.isSuccess() && ret.getData() != null) {
return Long.parseLong( ret.getData().toString());
}
return null;
} private Long finish(Long id, Integer taskStatus, String fileUrl, Integer total, Integer successTotal, String remark, String dataFlag) { DataFileTaskDTO taskDTO = new DataFileTaskDTO();
taskDTO.setId(id);
taskDTO.setTaskStatus(taskStatus);
taskDTO.setFileUrl(fileUrl);
taskDTO.setTotal(total == null ? 0 : total);
taskDTO.setSuccessTotal(successTotal == null ? 0 : successTotal);
taskDTO.setRemark(remark + ",数据版本号:" + dataFlag); log.info("【导入商品】推送到磐石完成任务参数,dataFileTaskDTO:{}", JSONObject.toJSONString(taskDTO));
Result ret = remote.finsh(taskDTO);
log.info("【导入商品】推送到磐石完成任务返回结果,ret:{}", JSONObject.toJSONString(ret));
if (!CheckUtils.isNull(ret) && ret.isSuccess()) {
return (Long) ret.getData();
}
return null;
} /**
* 获取用户名
*
* @return
*/
private String getUserName() {
// 获取当前用户
String userName = "";
LoginUserVo loginUserVo = UserVoThreadLocal.get();
if (Objects.nonNull(loginUserVo)) {
userName = loginUserVo.getUserName();
}
return userName;
} /**
* 获取真实姓名
*
* @return
*/
private String getRealName() {
// 获取当前用户
String realName = "";
LoginUserVo loginUserVo = UserVoThreadLocal.get();
if (Objects.nonNull(loginUserVo)) {
realName = loginUserVo.getRealName();
}
return realName;
}

导出:

1、导出controller

/**
* 导出维护记录
* @param vo
*/
@PostMapping("/download")
@ApiOperation(value = "采购单下载")
public Result<String> exportRecord(@RequestBody PurchaseOrderHeadVO vo) {
purchaseManageService.exportRecord(vo);
return Result.success("导出成功");
}

2、serviceImpl

@Async
public void createRecordFile(PurchaseOrderHeadVO vo, String currentUserName, String realName,Long id,String dataFlag) {
log.info("【导出采购单】 createRecordFile 开始,参数:{},用户:{},开始时间:{} ,数据版本号:{}", JSON.toJSONString(vo), currentUserName, System.currentTimeMillis(), dataFlag);
// 任务注册
if (id == null) {
return;
}
// 生成文件类型
ByteArrayOutputStream out = null;
Map<String, Object> map = getStringObjectMap(vo);
// 根据条件查询
List<PurchaseOrderModel> list = purchaseOrderExtendMapper.listForEceport(map);
if (CollectionUtils.isEmpty(list)) {
log.info("【导出采购单】 createRecordFile 未查询到需要导出的数据,数据版本号:" + dataFlag);
finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", 0, 0, "查询数据为空", dataFlag);
return;
}
try {
// 批量生成文件,每个文件数据,最多 6万
List<PurchaseDownloadModel> modelList = new ArrayList<>();
for (PurchaseOrderModel entity : list) {
PurchaseDownloadModel model = new PurchaseDownloadModel();
BeanUtils.copyProperties(entity, model);
// 采购模型
model.setPurchaseMode(PurchaseModeDictEnum.getNameByCode(model.getPurchaseMode()));
// 采购类型
model.setPurchaseType(PurchaseTypeDictEnum.getNameByCode(model.getPurchaseType()));
// 采购状态
model.setStatus(PurchaseStatusEnum.getNameByCode(model.getStatus()));
// 业务线
model.setBusinessLine(PurchaseBusinessDictEnum.getNameByCode(model.getBusinessLine()));
modelList.add(model);
}
out = new ByteArrayOutputStream();
ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
if (modelList.size() > FILE_SIZE) {
List<List<PurchaseDownloadModel>> splitList = Lists.partition(modelList, FILE_SIZE);
for (int i = 0; i < splitList.size(); i++) {
//写一个sheet,
Sheet sheet = new Sheet(i + 1, 0, PurchaseDownloadModel.class);
writer.write(splitList.get(i), sheet);
}
} else {
//写一个sheet,
Sheet sheet = new Sheet(1, 0, PurchaseDownloadModel.class);
writer.write(modelList, sheet);
}
writer.finish();
CloudStorageService oss = oSSFactory.build();
String path = oss.getDefaultPath("/采购单导出.xlsx");
String url = oss.upload((out).toByteArray(), path);
finish(id, DataFileTaskStatusEnum.SUCCESS.getType(), url, list.size(), list.size(), "导出成功", dataFlag);
log.info("【导出采购单】 createRecordFile 数据版本号:" + dataFlag + ",生成文件url:" + url);
} catch (Exception e) {
log.error("【导出采购单】 createRecordFile 数据版本号:" + dataFlag + ",导出报错: " + e.getMessage(), e);
// 发生异常,删除文件
finish(id, DataFileTaskStatusEnum.FAIL.getType(), "", list.size(), 0, "导出报错,数版本号:" + dataFlag, dataFlag);
} finally {
try {
if (out != null) {
out.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
log.info("【导出采购单】 createRecordFile 数据版本号:" + dataFlag + ",结束,时间:" + System.currentTimeMillis());
}

另外建议参考:https://github.com/HowieYuan/easyexcel-encapsulation

easyExcel用于导入导出的更多相关文章

  1. 使用Layui、Axios、Springboot(Java) 实现EasyExcel的导入导出(浏览器下载)

    实现EasyExcel的导入导出(浏览器下载) 实现三个按钮的功能,但是却花费了一天的时间包括总结. 使用到的技术:springboot layui axios EasyExcel mybatis-p ...

  2. 使用VUE+SpringBoot+EasyExcel 整合导入导出数据

    使用VUE+SpringBoot+EasyExcel 整合导入导出数据 创建一个普通的maven项目即可 项目目录结构 1 前端 存放在resources/static 下 index.html &l ...

  3. PL/SQLDeveloper导入导出Oracle数据库方法

    前一篇博客介绍了Navicat工具备份Oracle的方法,这篇博客介绍一下使用PL/SQL Developer工具导入导出Oracle数据库的方法. PL/SQL Developer是Oracle数据 ...

  4. 分享一次Oracle数据导入导出经历

    最近工作上有一个任务要修改一个比较老的项目,分公司这边没有这个项目数据库相关的备份,所以需要从正式环境上面导出数据库备份出来在本地进行部署安装,之前在其它项目的时候也弄过这个数据库的部署和安装,也写了 ...

  5. PL/SQL Developer导入导出Oracle数据库方法

    前一篇博客介绍了Navicat工具备份Oracle的方法.这篇博客介绍一下使用PL/SQL Developer工具导入导出Oracle数据库的方法. PL/SQL Developer是Oracle数据 ...

  6. java使用户EasyExcel导入导出excel

    使用alibab的EasyExce完成导入导出excel 一.准备工作 1.导包 <!-- poi 相关--> <dependency> <groupId>org. ...

  7. SpringCloud微服务实战——搭建企业级开发框架(三十):整合EasyExcel实现数据表格导入导出功能

      批量上传数据导入.数据统计分析导出,已经基本是系统必不可缺的一项功能,这里从性能和易用性方面考虑,集成EasyExcel.EasyExcel是一个基于Java的简单.省内存的读写Excel的开源项 ...

  8. .Net MVC 导入导出Excel总结(三种导出Excel方法,一种导入Excel方法) 通过MVC控制器导出导入Excel文件(可用于java SSH架构)

    .Net MVC  导入导出Excel总结(三种导出Excel方法,一种导入Excel方法) [原文地址] 通过MVC控制器导出导入Excel文件(可用于java SSH架构)   public cl ...

  9. Sqoop -- 用于Hadoop与关系数据库间数据导入导出工作的工具

    Sqoop是一款开源的工具,主要用于在Hadoop相关存储(HDFS.Hive.HBase)与传统关系数据库(MySql.Oracle等)间进行数据传递工作.Sqoop最早是作为Hadoop的一个第三 ...

随机推荐

  1. numpy中的mean()函数

    本文链接:https://blog.csdn.net/lilong117194/article/details/78397329mean() 函数定义:numpy.mean(a, axis, dtyp ...

  2. pip错误 ImportError: No module named 'pip_internal'

    ubuntu16.04 - wget https://bootstrap.pypa.io/get-pip.py --no-check-certificate sudo python get-pip.p ...

  3. JS正则表达式使用

    <script type="text/javascript"> function SubmitCk() { var reg = /^([a-zA-Z0-9]+[_|\_ ...

  4. Android studio 运行打包 Ionic 项目

    1.创建项目 ionic start myapp tabs 2.cd 到项目文件夹中 3.ionic cordova platfrom add android 执行这个命令后建议修改一下应用包名称,参 ...

  5. Qt编写自定义控件69-代码行数统计

    一.前言 代码行数统计主要用来统计项目中的所有文件的代码行数,其中包括空行.注释行.代码行,可以指定过滤拓展名,比如只想统计.cpp的文件,也可以指定文件或者指定目录进行统计.写完这个工具第一件事情就 ...

  6. k8s-基础环境配置(六)

    hostname配置1)修改主机名hostnamectl set-hostname xxx2)加入主机映射vim /etc/hosts……关闭selinuxsed -i '/^SELINUX/s/=. ...

  7. v关于使用Glide加载图片失败时显示自己特定的图片

    Glide是Android加载图片的一个框架. 常用加载图片到imageView:Glide.with(this).load(url).into(ImageView imageview). 当加载失败 ...

  8. clientHeight,offsetHeight,scrollHeight迷一样的三个值

    https://blog.csdn.net/qq_39083004/article/details/78498178 https://www.imooc.com/article/17571  推荐 o ...

  9. vue-cli4.0 基于 antd-design-vue 二次封装发布到 npm 仓库

    1. 安装 cli npm install -g @vue/cli vue create winyh-ui 2.安装 antd-design-vue cnpm i ant-design-vue --s ...

  10. HtmlHelper介绍

    目录 什么是HtmlHelper? 为什么要使用HtmlHelper? 清爽简单 修改路由不用改连接 很早就知道这个了,但是我一直不用.今天看了看书,准备以后都使用这个 什么是HtmlHelper? ...