赞
踩
@Data public class EmailImportParam implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "数据添加方式 1 系统自动通过邮箱域名查找备案的公司名称 2 手动输入") @NotNull @ExcelProperty(index = 0) private Integer dataType; @ApiModelProperty(value = "备用公司名称") @ExcelProperty(index = 1) private String inputCompanyName; @ApiModelProperty(value = "邮箱地址") @NotBlank @ExcelProperty(index = 2) private String email; }
- 如果不使用标题
@ExcelProperty(index = 0)
,标题从0
开启- 如果使用标题
@ExcelProperty("数据添加方式")
接口实现
@Override
@SneakyThrows
public Boolean importExcel(MultipartFile file) {
EasyExcel.read(file.getInputStream(), EmailImportParam.class, new EmailDataListener(this)).sheet().doRead();
return true;
}
添加EmailDataListener
package com.tophant.pentestinfoinv.listener; import cn.hutool.json.JSONUtil; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.util.ListUtils; import com.tophant.pentestinfoinv.common.domain.query.EmailAddParam; import com.tophant.pentestinfoinv.common.domain.query.EmailImportParam; import com.tophant.pentestinfoinv.service.IEmailService; import lombok.extern.slf4j.Slf4j; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * @Description email excel导入监听类 * @Author WanFei * @Date 2022/7/4 16:43 **/ @Slf4j public class EmailDataListener implements ReadListener<EmailImportParam> { /** * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收 */ private static final int BATCH_COUNT = 100; private List<EmailImportParam> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); /** * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。 */ private IEmailService emailService; /** * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来 * * @param emailService */ public EmailDataListener(IEmailService emailService) { this.emailService = emailService; } /** * 这个每一条数据解析都会来调用 * * @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()} * @param context */ @Override public void invoke(EmailImportParam data, AnalysisContext context) { log.info("解析到一条数据:{}", JSONUtil.toJsonStr(data)); cachedDataList.add(data); // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM if (cachedDataList.size() >= BATCH_COUNT) { saveData(); // 存储完成清理 list cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); } } /** * 所有数据解析完成了 都会来调用 * * @param context */ @Override public void doAfterAllAnalysed(AnalysisContext context) { // 这里也要保存数据,确保最后遗留的数据也存储到数据库 saveData(); log.info("所有数据解析完成!"); } /** * 加上存储数据库 */ private void saveData() { log.info("{}条数据,开始存储数据库!", cachedDataList.size()); List<EmailAddParam> emailAddParams = cachedDataList.stream().map(emailImportParam -> new EmailAddParam() .setEmails(Set.of(emailImportParam.getEmail())) .setDataType(emailImportParam.getDataType()) .setInputCompanyName(emailImportParam.getInputCompanyName())) .collect(Collectors.toList()); emailAddParams.forEach(emailService::create); log.info("存储数据库成功!"); } }
@Override @SneakyThrows public Boolean importExcel(MultipartFile file) { File newFile = MultipartFileUtil.multipartFileToFile(file); Assert.isFalse(ObjectUtil.isNull(file) || ObjectUtil.isNull(newFile), "文件不能为空!"); // 获取文件类型 String fileType = FileUtil.getType(newFile); log.info("上传文件的扩展名: {}", fileType); Assert.notNull(fileType, "上传文件拓展名为空!"); Assert.isTrue(StrUtil.containsAnyIgnoreCase(fileType, "xls", "xlsx"), StrUtil.format("不允许上传文件类型: {}", fileType)); List<EmailImportParam> emailList = new ArrayList<>(); List<String> emptyList = new ArrayList<>(); EasyExcel.read(file.getInputStream()).head(EmailImportParam.class) .sheet() .registerReadListener(new AnalysisEventListener<EmailImportParam>() { @Override public void invoke(EmailImportParam data, AnalysisContext context) { // 获取当前index Integer currentRowNum = context.readRowHolder().getRowIndex(); String errorMsg = ""; // 检查非空 EmailDataTypeEnum emailDataTypeEnum = EnumUtil.likeValueOf(EmailDataTypeEnum.class, data.getDataType()); if (ObjectUtil.isNull(emailDataTypeEnum)) { errorMsg = errorMsg.concat("数据添加方式 不能为空"); } if (emailDataTypeEnum == EmailDataTypeEnum.INPUT && StrUtil.isBlank(data.getInputCompanyName())) { errorMsg = errorMsg.concat("备用公司名称 不能为空"); } if (StrUtil.isBlank(data.getEmail())) { errorMsg = errorMsg.concat("邮箱地址 不能为空"); } if (StrUtil.isNotBlank(errorMsg)) { errorMsg = StrUtil.format("第 {} 行 ", currentRowNum + 1).concat(errorMsg); emptyList.add(errorMsg); } emailList.add(data); } @Override public void doAfterAllAnalysed(AnalysisContext context) { log.info("数据读取完毕"); } }).doRead(); Assert.isFalse(CollUtil.isNotEmpty(emptyList), "邮箱: {}", CollUtil.join(emptyList, ", ")); // 检查重复邮箱 String repeatEmails = emailList .stream() .collect(Collectors.groupingBy(EmailImportParam::getEmail, Collectors.counting())) .entrySet() .stream() .filter(e -> e.getValue() > 1) .map(Map.Entry::getKey) .collect(Collectors.joining(", ")); Assert.isFalse(StrUtil.isNotBlank(repeatEmails), "邮箱: {}重复, 请检查excel文件", repeatEmails); Set<String> emails = emailList.stream().map(EmailImportParam::getEmail).collect(Collectors.toSet()); InfoInvUtil.checkEmail(emails); // 查询已存在邮箱 String existEmails = this.lambdaQuery() .eq(Email::getDelFlag, false) .in(Email::getEmail, emails) .select(Email::getEmail) .list() .stream() .map(Email::getEmail) .collect(Collectors.joining(", ")); Assert.isFalse(StrUtil.isNotBlank(existEmails), StrUtil.format("邮箱: {} 已存在, 请检查excel文件", existEmails)); // 添加到数据库 List<EmailAddParam> emailAddParams = emailList.stream().map(emailImportParam -> new EmailAddParam() .setEmails(Set.of(emailImportParam.getEmail())) .setDataType(emailImportParam.getDataType()) .setInputCompanyName(emailImportParam.getInputCompanyName())) .collect(Collectors.toList()); emailAddParams.forEach(this::create); return true; }
MultipartFileUtil
工具类
package com.tophant.pentestinfoinv.common.utils; import lombok.extern.slf4j.Slf4j; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.util.Objects; /** * File转换工具 * * @author zhoqua.luo@tophant.com * @date 06-21-0021-2021 */ @Slf4j public class MultipartFileUtil { /** * MultipartFile转换为File * * @param file multipartFile * @return File * @throws Exception */ public static File multipartFileToFile(MultipartFile file) { try { File toFile = null; if (file.equals("") || file.getSize() <= 0) { file = null; } else { InputStream ins = null; ins = file.getInputStream(); toFile = new File(Objects.requireNonNull(file.getOriginalFilename())); inputStreamToFile(ins, toFile); ins.close(); } return toFile; } catch (Exception e) { log.warn("MultipartFile转化为File失败!"); return null; } } /** * 获取流文件 * @param ins * @param file */ private static void inputStreamToFile(InputStream ins, File file) { try { OutputStream os = new FileOutputStream(file); int bytesRead = 0; byte[] buffer = new byte[8192]; while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) { os.write(buffer, 0, bytesRead); } os.close(); ins.close(); } catch (Exception e) { e.printStackTrace(); } } }
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
EasyExcel.write(byteArrayOutputStream, EmailExcelVO.class)
// 注册自定义拦截器
.registerWriteHandler(new CustomCellWriteConfig())
.registerWriteHandler(new CustomColumnWidthConfig())
.registerWriteHandler(new CustomRowHeightConfig())
.sheet("邮箱")
.doWrite(excelVOList);
package com.tophant.component.starter.excel.common.config; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import org.apache.poi.ss.usermodel.*; import java.util.List; /** * @Description 设置样式 * @Author WanFei * @Date 2022/5/13 12:13 */ public class CustomCellWriteConfig implements CellWriteHandler { private Workbook workbook; private CellStyle cellStyle; @Override public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { if (workbook == null) { // 放在里面,避免重复创建对象,导致报错 The maximum number of Cell Styles was exceeded. You can define up to 64000 style in a .xlsx Workbook workbook = writeSheetHolder.getSheet().getWorkbook(); cellStyle = workbook.createCellStyle(); // 居中 cellStyle.setAlignment(HorizontalAlignment.LEFT); cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); cellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); // 设置边框 cellStyle.setBorderBottom(BorderStyle.THIN); cellStyle.setBorderLeft(BorderStyle.THIN); cellStyle.setBorderRight(BorderStyle.THIN); cellStyle.setBorderTop(BorderStyle.THIN); // 自动换行 cellStyle.setWrapText(true); } // 配置生效 cell.setCellStyle(cellStyle); } }
package com.tophant.component.starter.excel.common.config; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.metadata.data.CellData; import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Sheet; import org.springframework.util.CollectionUtils; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @Description 自适应宽度 * @Author WanFei * @Date 2022/5/13 13:59 */ public class CustomColumnWidthConfig extends AbstractColumnWidthStyleStrategy { private Map<Integer, Map<Integer, Integer>> CACHE = new HashMap<>(); @Override protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer integer, Boolean isHead) { boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList); if (needSetWidth) { Map<Integer, Integer> maxColumnWidthMap = CACHE.computeIfAbsent(writeSheetHolder.getSheetNo(), k -> new HashMap<>()); Integer columnWidth = this.dataLength(cellDataList, cell, isHead); if (columnWidth >= 0) { if (columnWidth > 254) { columnWidth = 254; } Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex()); if (maxColumnWidth == null || columnWidth > maxColumnWidth) { maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth); Sheet sheet = writeSheetHolder.getSheet(); sheet.setColumnWidth(cell.getColumnIndex(), columnWidth * 256); } } } } /** * 计算长度 * @param cellDataList * @param cell * @param isHead * @return */ private Integer dataLength(List<WriteCellData<?>> cellDataList, Cell cell, Boolean isHead) { if (isHead) { return cell.getStringCellValue().getBytes().length; } else { CellData<?> cellData = cellDataList.get(0); CellDataTypeEnum type = cellData.getType(); if (type == null) { return -1; } else { switch (type) { case STRING: // 换行符(数据需要提前解析好) int index = cellData.getStringValue().indexOf("\n"); return index != -1 ? cellData.getStringValue().substring(0, index).getBytes().length + 1 : cellData.getStringValue().getBytes().length + 1; case BOOLEAN: return cellData.getBooleanValue().toString().getBytes().length; case NUMBER: return cellData.getNumberValue().toString().getBytes().length; default: return -1; } } } } }
package com.tophant.component.starter.excel.common.config; import com.alibaba.excel.write.style.row.AbstractRowHeightStyleStrategy; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import java.util.Iterator; /** * @Description 自适应行高 * @Author WanFei * @Date 2022/5/13 14:03 */ public class CustomRowHeightConfig extends AbstractRowHeightStyleStrategy { /** * 默认高度 */ private static final Integer DEFAULT_HEIGHT = 300; @Override protected void setHeadColumnHeight(Row row, int relativeRowIndex) { } @Override protected void setContentColumnHeight(Row row, int relativeRowIndex) { Iterator<Cell> cellIterator = row.cellIterator(); if (!cellIterator.hasNext()) { return; } // 默认为 1行高度 Integer maxHeight = 1; while (cellIterator.hasNext()) { Cell cell = cellIterator.next(); switch (cell.getCellType()) { case STRING: if (cell.getStringCellValue().contains("\n")) { int length = cell.getStringCellValue().split("\n").length; maxHeight = Math.max(maxHeight, length); } break; default: break; } } row.setHeight((short) (maxHeight * DEFAULT_HEIGHT)); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。