0.前提-----引入依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.1</version> </dependency>
1.导入
1.实体
package org.mnur.marketing.api.dto.vo; import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; /** * 消息活动-用户导入实体 */ @Data public class UserInputVo { @ExcelProperty("用户ID") private Long consumerId; @ExcelProperty("用户手机号") private String phone; }
2.导入模板监听器
package org.mnur.marketing.excel; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.exception.ExcelDataConvertException; import org.hzero.core.exception.MessageException; import java.util.ArrayList; import java.util.List; /** * 导入模板监听器 * @author wy * @date 2022-03-14 15:37 **/ public class UploadDataListener<T> extends AnalysisEventListener<T> { /**数据集*/ private final List<T> list = new ArrayList<>(); public List<T> getList(){ return this.list; } /** * 每条数据都会进入 * @param object: * @param analysisContext: */ @Override public void invoke(T object, AnalysisContext analysisContext) { if(null != analysisContext) { this.list.add(object); } } /** * 数据解析完调用 * @param analysisContext: */ @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } /** * 异常时调用 * @param exception: * @param context: * @throws Exception */ @Override public void onException(Exception exception, AnalysisContext context) throws Exception { // 数据解析异常 if (exception instanceof ExcelDataConvertException) { ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception; throw new MessageException("第" + excelDataConvertException.getRowIndex() + "行" + excelDataConvertException.getColumnIndex() + "列" + "数据解析异常"); } // 其他异常... } }
3.业务操作
/** * 解析上传文件集合 * @param urlList 文件地址集合 * @return 电话号码集合 */ private HashSet<String> parsingFile(List<String> urlList){ HashSet<String> hashSet = new HashSet<>(); urlList.forEach(url->{ HashSet<String> set = null; try { set = parsing(getInputStream(url), new UserInputVo(), null); } catch (IOException e) { e.printStackTrace(); } hashSet.addAll(set); }); return hashSet; } /** * 文件流解析获取单个上传文件集合 * @param inputStream 文件流 * @param vo 对象 * @param analysisContext analysisContext */ public HashSet<String> parsing(InputStream inputStream, UserInputVo vo, AnalysisContext analysisContext) { HashSet<String> hashSet = new HashSet<>(); UploadDataListener<UserInputVo> uploadDataListener = new UploadDataListener<UserInputVo>(); //开始处理数据 uploadDataListener.invoke(vo,analysisContext); EasyExcelFactory.read(inputStream,UserInputVo.class,uploadDataListener).sheet("Sheet1").doRead(); List<UserInputVo> list = uploadDataListener.getList(); if (CollectionUtils.isEmpty(list)) { return hashSet; } else { list.forEach(vv->{ hashSet.add(vv.getPhone()); }); } return hashSet; } /** * 根据地址获取文件流 * * @param strUrl 文件在线地址 * @return */ private static InputStream getInputStream(String strUrl) throws IOException { //把地址转换成URL对象 URL url = new URL(strUrl); //创建http链接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //设置超时间为3秒 conn.setConnectTimeout(3 * 1000); //防止屏蔽程序抓取而返回403错误 conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); //得到输入流 return conn.getInputStream(); }
4.注意:
本示例传入的是阿里云文件地址集合进行解析
2.导出
1.自定义导出
1.entity
@Data @NoArgsConstructor @ApiModel("商品列表导出-列表专用") public class GoodsVO { @ApiModelProperty(value = "商品编码") @ExcelProperty(value = "商品编码") private String goodsCode; @ApiModelProperty(value = "商品全称") @ExcelProperty(value = "商品全称") private String goodsName; }
@Data @ApiModel("导出列表公用头") @ColumnWidth(value = 50) @HeadRowHeight(value = 20) @ContentRowHeight(value = 18) public class ExcelHeadVO { @ColumnWidth(value = 30) @ExcelProperty(value = "项目") private String project; @ColumnWidth(value = 30) @ExcelProperty(value = "内容") private String content;}
2.controller
/** * 出接口 * @param obj 查询参数 type 类型 1:商品 2:点位 3:库存变更 4:交易订单 5:支付订单 6:退款订单 * @param response 响应 */ @GetMapping("/export") @ApiOperation(value = "列表导出(type 类型 1:商品 2:点位 3:库存变更 4:交易订单 5:支付订单 6:退款订单)", httpMethod = "GET") @Permission(level = ResourceLevel.ORGANIZATION, permissionLogin = true) public void export(String obj, HttpServletResponse response, @PathVariable String organizationId) { exportService.export(response, obj); }
3.service
/** * 导出接口 * @param response 响应 * @param obj 对象 */ void export(HttpServletResponse response, String obj);
4.impl
/*商品库列表*/ private static final String GH = "[{\"project\":\"\",\"content\":\"\"},{\"project\":\"★ 操作信息:\",\"content\":\"\"},{\"project\":\"系统\",\"content\":\"蒙牛新的吧/智能零售运营管理平台\"},{\"project\":\"模块/页面\",\"content\":\"商品/商品库/列表页\"},{\"project\":\"业务操作\",\"content\":\"导出数据\"},{\"project\":\"操作经办\",\"content\":\"\"},{\"project\":\"操作时间\",\"content\":\"\"},{\"project\":\"数据明细数量(条)\",\"content\":\"\"},{\"project\":\"\",\"content\":\"\"},{\"project\":\"★ 数据筛选:\",\"content\":\"\"}]";/** * 导出数据 * @param response 响应 * @param obj 对象 type 类型 1:商品 2:点位 3:库存变更 4:交易订单 5:支付订单 6:退款订单 */ @Override public void export(HttpServletResponse response,String obj){ JSONObject jsonObject = JSONObject.parseObject(obj); if(null != jsonObject && null != jsonObject.getString("type")) { Integer tp = jsonObject.getInteger("type"); //根据类型判断详情 switch (tp) { case 1: this.exportGoodsList(response, obj); break; default: throw new MessageException("导出类型错误", BasePlusConstants.HttpResponseCode.INTERNAL_SERVER_ERROR); } } }/** * 导出商品库列表 * @param obj 查询参数 */ private void exportGoodsList(HttpServletResponse response,String obj){ //查询参数 Goods qo = JSONObject.parseObject(obj , Goods.class) == null ? new Goods() : JSONObject.parseObject(obj , Goods.class); //详细数据 List<GoodsVO> lit = goodsMapper.queryByCondition(qo); //概述 JSONObject ob = getJsonObject(obj); List<ExcelHeadVO> list = JSON.parseArray(GH, ExcelHeadVO.class); getHead(list, CollectionUtils.isEmpty(lit), lit.size()); //组装查询条件 ExcelGoodsEnum.getEumValueList().forEach(str->{ ExcelHeadVO vo = getExcelHeadVO(qo, ob, str); list.add(vo); }); try { ExcelWriter excelWriter = getExcelWriter(response); WriteSheet writeSheet = EasyExcel.writerSheet(0, "操作概要").head(ExcelHeadVO.class).build(); excelWriter.write(list, writeSheet); writeSheet = EasyExcel.writerSheet(1, "数据明细").head(GoodsVO.class).build(); excelWriter.write(lit, writeSheet); excelWriter.finish(); } catch (Exception e) { e.printStackTrace(); } }/** * 组装头部信息 * @param list 集合 * @param empty 类型 * @param size 数量 */ private void getHead(List<ExcelHeadVO> list, boolean empty, int size) { //组装头部变动信息 Optional.of(list).orElse(new ArrayList<>()).forEach(vv -> { if ("操作经办".equals(vv.getProject())) { vv.setContent(DetailsHelper.getUserDetails().getUsername()); } if ("操作时间".equals(vv.getProject())) { vv.setContent(SDF.format(new Date())); } if ("数据明细数量(条)".equals(vv.getProject())) { vv.setContent(empty ? "0" : size + ""); } }); }
2.模板导出
注意事项:
1.准备模板
2.切忌实体类上一样需要注解支持
3.文件地址解析
1.根据本地文件地址解析文件
File file = new File("C:\\Users\\EDY\\Desktop\\mmm.xlsx"); FileItem fileItem = createFileItem(file); MultipartFile multipartFile = new CommonsMultipartFile(fileItem);private static FileItem createFileItem(File file) { FileItemFactory factory = new DiskFileItemFactory(16, null); FileItem item = factory.createItem("textField", "text/plain", true, file.getName()); int bytesRead = 0; byte[] buffer = new byte[8192]; try { FileInputStream fis = new FileInputStream(file); OutputStream os = item.getOutputStream(); while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) { os.write(buffer, 0, bytesRead); } os.close(); fis.close(); } catch (IOException e) { e.printStackTrace(); } return item; }
2.根据在线地址解析文件
/** * 根据地址获取文件流 * * @param strUrl 文件在线地址 * @return */ private static InputStream getInputStream(String strUrl) throws IOException { //把地址转换成URL对象 URL url = new URL(strUrl); //创建http链接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //设置超时间为3秒 conn.setConnectTimeout(3 * 1000); //防止屏蔽程序抓取而返回403错误 conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); //得到输入流 return conn.getInputStream(); }/**
* 获取封装得MultipartFile
*
* @param inputStream inputStream
* @param fileName fileName
* @return MultipartFile
*/
public MultipartFile getMultipartFile(InputStream inputStream, String fileName) {
FileItem fileItem = createFileItem(inputStream, fileName);
//CommonsMultipartFile是feign对multipartFile的封装,但是要FileItem类对象
return new CommonsMultipartFile(fileItem);
}