From 2c2c4c2cf984119902c979cf8bb40ced091d0ca8 Mon Sep 17 00:00:00 2001 From: jing's Date: Thu, 21 Mar 2024 23:27:26 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E5=8A=A8=E7=A0=B4=E8=B0=83=E6=95=B4?= =?UTF-8?q?=20=E9=87=8D=E6=9E=84excel=E8=A7=A3=E6=9E=90=EF=BC=9A1.?= =?UTF-8?q?=E7=89=A9=E6=96=99=E5=8C=B9=E9=85=8D=E8=B0=83=E6=95=B4=202.?= =?UTF-8?q?=E5=AF=BC=E5=87=BAexcel=20=E8=B0=83=E6=95=B4=203.=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E6=A8=A1=E7=89=88=E6=9B=BF=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bomnew/constant/OptionalBomConstant.java | 4 +- .../bomnew/excel/ExportDeviceHelper.java | 58 +- .../bomnew/excel/ImportExcelField.java | 11 +- .../service/aggreg/OptionalExcelService.java | 542 +++++++++++------- .../template/importDataTemplate.xlsx | Bin 12267 -> 14437 bytes 5 files changed, 394 insertions(+), 221 deletions(-) diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/constant/OptionalBomConstant.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/constant/OptionalBomConstant.java index bf8d7339..5959ea4b 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/constant/OptionalBomConstant.java +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/constant/OptionalBomConstant.java @@ -76,8 +76,8 @@ public class OptionalBomConstant { public enum ExcelErrorTagEnum implements ValueEnum { NO(0, "无错误"), REPEAT(1, "重复的标配"), - MATERIA_NO_UNKOWN(2, "无物料号"), - ALL(3, "同时满足(重复标配、无物料号)"); + MATERIA_NO_UNKOWN(2, "主数据无匹配物料号"), + ALL(3, "同时满足(重复标配、主数据无匹配物料号)"); private final Integer value; private final String description; diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ExportDeviceHelper.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ExportDeviceHelper.java index 73521db7..9cf460aa 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ExportDeviceHelper.java +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ExportDeviceHelper.java @@ -28,6 +28,8 @@ import org.apache.poi.xssf.usermodel.XSSFColor; import java.io.OutputStream; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /**' * 移动破导出设备 @@ -49,7 +51,7 @@ public class ExportDeviceHelper { .needHead(false)//是否需要head .build(); - buildHeader(2, voObj.getDeviceInfo(), sheet, writer, tableNoCounting); + buildHeader(4, voObj.getDeviceInfo(), sheet, writer, tableNoCounting); buildList(voObj.getSingleList(), sheet, writer, tableNoCounting); writer.finish(); @@ -177,15 +179,21 @@ public class ExportDeviceHelper { case 0: columnWidth = 50; break; + case 1: - columnWidth = 70; + columnWidth = 20; break; case 2: - columnWidth = 20; + columnWidth = 70; break; case 3: - columnWidth = 40; + columnWidth = 20; + + break; + case 4: + + columnWidth = 20; break; default: @@ -200,13 +208,10 @@ public class ExportDeviceHelper { // 自定义表头样式处理 if (context.getHead() != null && context.getHead().booleanValue()) { - if(cellIndex==0 || cellIndex ==1) { + if(cellIndex==0 || cellIndex ==1 || cellIndex ==2) { WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder(); Workbook workbook = writeSheetHolder.getSheet().getWorkbook(); - - CellStyle cellStyle = initCellStyle(workbook); - XSSFCellStyle xssfCellStyle = (XSSFCellStyle) workbook.createCellStyle(); xssfCellStyle.cloneStyleFrom(cellStyle); xssfCellStyle.getFont().setBold(true); @@ -224,10 +229,11 @@ public class ExportDeviceHelper { } - if(cellIndex ==1){ + //合并选项头单元格 0~2 + if(cellIndex == 2){ WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder(); Sheet sheet = writeSheetHolder.getSheet(); - CellRangeAddress cellRangeAddress = new CellRangeAddress(rowIndex, rowIndex, 0, 1); + CellRangeAddress cellRangeAddress = new CellRangeAddress(rowIndex, rowIndex, 0, 2); sheet.addMergedRegion(cellRangeAddress); } @@ -270,11 +276,15 @@ public class ExportDeviceHelper { head2.add(""); List head3 = new ArrayList(); head3.add(""); + List head4 = new ArrayList(); + head4.add(""); + list.add(head0); list.add(head1); list.add(head2); list.add(head3); + list.add(head4); return list; } @@ -318,6 +328,7 @@ public class ExportDeviceHelper { cellList.add(StrUtil.format("{} {}", header.getDeviceNo(), header.getDeviceName())); List cellList2 = new ArrayList<>(); cellList2.add("选配内容"); + cellList2.add(""); //空格合并单元格 cellList2.add(""); cellList2.add("标配\\可选"); cellList2.add("备注"); @@ -327,7 +338,15 @@ public class ExportDeviceHelper { //写入表格 writer.write(rowList, sheet, table); } + boolean isContainChinese(String str) { + Pattern p = Pattern.compile("[\u4e00-\u9fa5]"); + Matcher m = p.matcher(str); + if (m.find()) { + return true; + } + return false; + } /** * 构建列表部分 */ @@ -348,11 +367,6 @@ public class ExportDeviceHelper { optionParentDrawingNoName = item1.getOptionDrawingNo(); List list2 = item1.getChild(); -// List cellList = new ArrayList<>(); -// cellList.add(opParentName); - - - for (OptionalEbomImportVO item2 : list2) { { @@ -363,15 +377,19 @@ public class ExportDeviceHelper { ImportExcelField excelField = new ImportExcelField(); excelField.setCellFirst(StrUtil.format("{} {}",optionChildDrawingNo,opChildName)); + excelField.setCellSecond(StrUtil.format("{}", item3.getMaterialNo())); + if(StrUtil.isEmpty(item3.getDrawingNo())) { - excelField.setCellSecond(StrUtil.format("{}", item3.getMaterialName())); - }else { - excelField.setCellSecond(StrUtil.format ("{} {}", item3.getDrawingNo(), item3.getMaterialName())); + excelField.setCellThird(StrUtil.format("{}", item3.getMaterialName())); + }else if(isContainChinese(item3.getDrawingNo())){ + excelField.setCellThird(StrUtil.format("{}", item3.getDrawingNo())); + }else{ + excelField.setCellThird(StrUtil.format ("{} {}", item3.getDrawingNo(), item3.getMaterialName())); } - excelField.setCellThird(StrUtil.format("{}",item3.getChooseStatus() == 1 ? "标配" : "可选")) ; - excelField.setCellFourth(item3.getRemak()); + excelField.setCellFourth(StrUtil.format("{}",item3.getChooseStatus() == 1 ? "标配" : "可选")); ; + excelField.setCellFifth(item3.getRemak()); items.add(excelField); } diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ImportExcelField.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ImportExcelField.java index 5f015c74..7f74b86f 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ImportExcelField.java +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/excel/ImportExcelField.java @@ -9,19 +9,22 @@ import lombok.Data; public class ImportExcelField{ @ExcelIgnore private Integer lineNo; - + //选项 @ExcelProperty(value="",index = 0) private String cellFirst; - + //物料 @ExcelProperty(value="",index = 1) private String cellSecond; - + //选配内容 @ExcelProperty(value="",index = 2) private String cellThird; - + //标配/可选 @ExcelProperty(value="",index = 3) private String cellFourth; + //备注 + @ExcelProperty(value="",index = 4) + private String cellFifth; diff --git a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/aggreg/OptionalExcelService.java b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/aggreg/OptionalExcelService.java index 6338cfd9..3ed9971f 100644 --- a/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/aggreg/OptionalExcelService.java +++ b/nflg_project_dev/nflg-bom-new/src/main/java/com/nflg/product/bomnew/service/aggreg/OptionalExcelService.java @@ -22,6 +22,7 @@ import com.nflg.product.bomnew.pojo.entity.OptionalEbomImportChildEntity; import com.nflg.product.bomnew.pojo.entity.OptionalEbomImportEntity; import com.nflg.product.bomnew.pojo.entity.OptionalEbomMainEntity; import com.nflg.product.bomnew.pojo.vo.BaseMaterialVO; +import com.nflg.product.bomnew.pojo.vo.BomNewMbomMiddleVO; import com.nflg.product.bomnew.service.*; import com.nflg.product.bomnew.service.domain.OptionalEBom.ConvertToMainHistory; import lombok.extern.slf4j.Slf4j; @@ -51,70 +52,56 @@ public class OptionalExcelService { @Resource private OptionalEbomImportService optionalEbomImportService; - private void parsecColumn3(List v1, OptionalEbomImportDTO optionalEbomImportLevel2Dto) { - AtomicInteger partTypeCount = new AtomicInteger(); - boolean tag=false; - //解析物料 - for (ImportExcelField item: - v1) { + /* + 解析物料 + */ + private void parseColumn3(List v1, OptionalEbomImportDTO optionalEbomImportLevel2Dto) { + AtomicInteger partTypeCount = new AtomicInteger(); + boolean tag = false; + int lineNo =v1.get(0).getLineNo(); + //解析物料 + for (ImportExcelField item : + v1) { if (StrUtil.isEmpty(item.getCellSecond())) { throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行, {} {}出现空物料数据", item.getLineNo(), optionalEbomImportLevel2Dto.getOptionName(), optionalEbomImportLevel2Dto.getOptionDrawingNo())); } if (StrUtil.isEmpty(item.getCellThird())) { + throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行, {} {}无选项数据", item.getLineNo(), optionalEbomImportLevel2Dto.getOptionName(), optionalEbomImportLevel2Dto.getOptionDrawingNo())); + } + + + if (StrUtil.isEmpty(item.getCellFourth())) { throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,物料信息{}未填写标配/可选", item.getLineNo(), item.getCellSecond())); } - //OCE-NFS780DP-037B-OPT:加装回料输送机(可选) - OptionalEbomImportChildDTO levelDto3 = new OptionalEbomImportChildDTO(); + OptionalEbomImportChildDTO levelDto3 = new OptionalEbomImportChildDTO(); if (CollectionUtil.isEmpty(optionalEbomImportLevel2Dto.getChild())) { optionalEbomImportLevel2Dto.setChild(new ArrayList()); } - String materialDesc = item.getCellSecond().trim(); - //替换统一格式 - // materialDesc = materialDesc.replace(":", ":"); - int optionChildPos=materialDesc.indexOf(" "); + String materialName = item.getCellThird().trim(); - if(optionChildPos<0){ - throw new NflgBusinessException(STATE.Error,StrUtil.format("第{}行,格式错误,选项使用空格分隔图号和名称 {}",item.getLineNo(), item.getCellSecond())); - } - levelDto3.setDrawingNo(StrUtil.sub(materialDesc, 0, optionChildPos)); - String materialName = StrUtil.subSuf(materialDesc, optionChildPos + 1); - -// if (StrUtil.isEmpty(levelDto3.getDrawingNo())) { -// throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,格式错误,解析后不包含物料图号", item.getLineNo(), item.getCellSecond())); -// } - - if (StrUtil.isEmpty(materialName)) { - throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,格式错误,解析后不包含物料名", item.getLineNo(), item.getCellSecond())); - } - - levelDto3.setMaterialName(materialName); levelDto3.setLineNo(item.getLineNo()); levelDto3.setPartType(OptionalBomConstant.PartTypeEnum.PART_TYPE_RADIO.getValue()); - //(标配) (可选) + levelDto3.setMaterialNo(item.getCellSecond()); levelDto3.setTag(materialName.contains("无")); - levelDto3.setMaterialDesc(materialDesc); -//多个无 + // levelDto3.setMaterialDesc(materialName); + // levelDto3.setMaterialNo(materialName); + // levelDto3.setMaterialName(materialName); + //多个无 if (tag && levelDto3.getTag()) { - throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,{} {} 包含多个无", item.getLineNo(),optionalEbomImportLevel2Dto.getOptionName(), optionalEbomImportLevel2Dto.getOptionDrawingNo())); - + throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,{} {} 包含多个无", item.getLineNo(), optionalEbomImportLevel2Dto.getOptionName(), optionalEbomImportLevel2Dto.getOptionDrawingNo())); } tag = levelDto3.getTag(); - -// if (levelDto3.getTag()) { -// levelDto3.setMaterialDesc(materialName); -// } - - if (item.getCellThird().contains("标配")) { + if (item.getCellFourth().contains("标配")) { levelDto3.setChooseStatus(OptionalBomConstant.ChooseStatusEnum.CHOOSE_STATUS_YES.getValue()); partTypeCount.getAndIncrement(); //包含多个标配 @@ -122,36 +109,129 @@ public class OptionalExcelService { levelDto3.setError(OptionalBomConstant.ExcelErrorTagEnum.REPEAT.getValue()); optionalEbomImportLevel2Dto.setError(true); - throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,{} {} 包含多个标配", item.getLineNo(),optionalEbomImportLevel2Dto.getOptionName(), optionalEbomImportLevel2Dto.getOptionDrawingNo())); + throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,{} {} 包含多个标配", item.getLineNo(), optionalEbomImportLevel2Dto.getOptionName(), optionalEbomImportLevel2Dto.getOptionDrawingNo())); } } else { levelDto3.setChooseStatus(OptionalBomConstant.ChooseStatusEnum.CHOOSE_STATUS_NO.getValue()); } - levelDto3.setRemak(item.getCellFourth()); + levelDto3.setRemak(item.getCellFifth()); optionalEbomImportLevel2Dto.getChild().add(levelDto3); -// levelDto3.setMaterialName(materialName.replace("(标配)", "").replace("(可选)", "")); -// levelDto3.setMaterialDesc(levelDto3.getMaterialDesc()); } + + + } - private void parsecColumn2(Map> listMap, OptionalEbomImportDTO optionalEbomImportDTO) { + + + + + + + +// private void parseColumn3(List v1, OptionalEbomImportDTO optionalEbomImportLevel2Dto) { +// AtomicInteger partTypeCount = new AtomicInteger(); +// boolean tag = false; +// //解析物料 +// for (ImportExcelField item : +// v1) { +// +// if (StrUtil.isEmpty(item.getCellSecond())) { +// throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行, {} {}出现空物料数据", item.getLineNo(), optionalEbomImportLevel2Dto.getOptionName(), optionalEbomImportLevel2Dto.getOptionDrawingNo())); +// } +// +// if (StrUtil.isEmpty(item.getCellThird())) { +// throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,物料信息{}未填写标配/可选", item.getLineNo(), item.getCellSecond())); +// } +// +// +// //OCE-NFS780DP-037B-OPT:加装回料输送机(可选) +// OptionalEbomImportChildDTO levelDto3 = new OptionalEbomImportChildDTO(); +// +// if (CollectionUtil.isEmpty(optionalEbomImportLevel2Dto.getChild())) { +// optionalEbomImportLevel2Dto.setChild(new ArrayList()); +// } +// +// +// String materialDesc = item.getCellSecond().trim(); +// //替换统一格式 +// +// int optionChildPos = materialDesc.indexOf(" "); +// +// if (optionChildPos < 0) { +// throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,格式错误,选项使用空格分隔图号和名称 {}", item.getLineNo(), item.getCellSecond())); +// } +// +// levelDto3.setDrawingNo(StrUtil.sub(materialDesc, 0, optionChildPos)); +// String materialName = StrUtil.subSuf(materialDesc, optionChildPos + 1); +// +//// if (StrUtil.isEmpty(levelDto3.getDrawingNo())) { +//// throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,格式错误,解析后不包含物料图号", item.getLineNo(), item.getCellSecond())); +//// } +// +// if (StrUtil.isEmpty(materialName)) { +// throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,格式错误,解析后不包含物料名", item.getLineNo(), item.getCellSecond())); +// } +// +// levelDto3.setMaterialName(materialName); +// levelDto3.setLineNo(item.getLineNo()); +// levelDto3.setPartType(OptionalBomConstant.PartTypeEnum.PART_TYPE_RADIO.getValue()); +// //(标配) (可选) +// levelDto3.setTag(materialName.contains("无")); +// levelDto3.setMaterialDesc(materialDesc); +// //多个无 +// if (tag && levelDto3.getTag()) { +// throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,{} {} 包含多个无", item.getLineNo(), optionalEbomImportLevel2Dto.getOptionName(), optionalEbomImportLevel2Dto.getOptionDrawingNo())); +// +// } +// tag = levelDto3.getTag(); +// +// if (item.getCellThird().contains("标配")) { +// levelDto3.setChooseStatus(OptionalBomConstant.ChooseStatusEnum.CHOOSE_STATUS_YES.getValue()); +// partTypeCount.getAndIncrement(); +// //包含多个标配 +// if (partTypeCount.get() > 1) { +// levelDto3.setError(OptionalBomConstant.ExcelErrorTagEnum.REPEAT.getValue()); +// optionalEbomImportLevel2Dto.setError(true); +// +// throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,{} {} 包含多个标配", item.getLineNo(), optionalEbomImportLevel2Dto.getOptionName(), optionalEbomImportLevel2Dto.getOptionDrawingNo())); +// } +// } else { +// levelDto3.setChooseStatus(OptionalBomConstant.ChooseStatusEnum.CHOOSE_STATUS_NO.getValue()); +// } +// +// levelDto3.setRemak(item.getCellFourth()); +// optionalEbomImportLevel2Dto.getChild().add(levelDto3); +// +// +// } +// } + + /** + * 解析子项 + + */ + private void parseOptionColumn2(Map> listMap, OptionalEbomImportDTO optionalEbomImportDTO) { + + List optionList=new ArrayList(); //子项 listMap.forEach((k, v) -> { - if(CollectionUtil.isEmpty(v)){ - throw new NflgBusinessException(STATE.Error,StrUtil.format("{} {} 下无物料数据",optionalEbomImportDTO.getOptionDrawingNo(),optionalEbomImportDTO.getOptionName())); + if (CollectionUtil.isEmpty(v)) { + throw new NflgBusinessException(STATE.Error, StrUtil.format("{} {} 下无物料数据", optionalEbomImportDTO.getOptionDrawingNo(), optionalEbomImportDTO.getOptionName())); } - int optionChildPos=k.indexOf(" "); + k= k.replace("\t", " "); + int optionChildPos = k.indexOf(" "); - if(optionChildPos<0){ - throw new NflgBusinessException(STATE.Error,StrUtil.format("第{}行,格式错误,选项使用空格分隔图号和名称",v.get(0).getLineNo())); + if (optionChildPos < 0) { + throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,格式错误,选项使用空格分隔图号和名称", v.get(0).getLineNo())); } OptionalEbomImportDTO optionalEbomImportL2 = new OptionalEbomImportDTO(); - optionalEbomImportL2.setOptionDrawingNo(StrUtil.sub(k,0,optionChildPos)); - optionalEbomImportL2.setOptionName(StrUtil.subSuf(k,optionChildPos+1)); + optionalEbomImportL2.setOptionDrawingNo(StrUtil.sub(k, 0, optionChildPos)); + optionalEbomImportL2.setOptionName(StrUtil.subSuf(k, optionChildPos + 1)); if (StrUtil.isEmpty(optionalEbomImportL2.getOptionDrawingNo())) { throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,格式错误,解析后没有图号", v.get(0).getLineNo())); @@ -161,184 +241,263 @@ public class OptionalExcelService { throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,格式错误,解析后没有选项名", v.get(0).getLineNo())); } - if (CollectionUtil.isEmpty(optionalEbomImportDTO.getChild())) { optionalEbomImportDTO.setChild(new ArrayList()); } optionalEbomImportDTO.getChild().add(optionalEbomImportL2); - parsecColumn3(v, optionalEbomImportL2); + parseColumn3(v, optionalEbomImportL2); + optionList.addAll(optionalEbomImportL2.getChild()); + }); + //检查选项下是否包含重复物料 + Map frequencyMap = optionList.stream().collect(Collectors.groupingBy(OptionalEbomImportChildDTO::getMaterialNo, Collectors.counting())); + List duplicates = frequencyMap.entrySet().stream() + .filter(entry -> entry.getValue() > 1) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + if(CollectionUtil.isNotEmpty(duplicates)){ + String result = duplicates.stream().collect(Collectors.joining(",")); + throw new NflgBusinessException(STATE.Error, StrUtil.format(" {} {} 选项下有相同物料号{}", optionalEbomImportDTO.getOptionDrawingNo(),optionalEbomImportDTO.getOptionName(),result)); + } + + //选项下同步主数据 + SpringUtil.getBean(MaterialMainService.class).intiMaterialInfo(optionList,OptionalEbomImportChildDTO::getMaterialNo); + for (OptionalEbomImportChildDTO childDTO : optionList) { + //!childDTO.getTag() && + if (StringUtils.isEmpty(childDTO.getDrawingNo())) { + childDTO.setError(childDTO.getError() | OptionalBomConstant.ExcelErrorTagEnum.MATERIA_NO_UNKOWN.getValue()); + + optionalEbomImportDTO.setError(true); + } + } + + + } - private OptionalEbomImportExcelDTO parsecColumn1(List list) { +// +// private OptionalEbomImportExcelDTO parsecColumn1(List list) { +// OptionalEbomImportExcelDTO optionalEbomInportExcelDTO = new OptionalEbomImportExcelDTO(); +// //第一行设备信息 +// ImportExcelField device = list.get(0); +// optionalEbomInportExcelDTO.setDeviceInfo(parseDevcieInfo(device)); +// +// +// String name = ""; +// //相同类 +// List classList = new ArrayList<>(); +// //跳过 第一行标题 选配内容 标配\可选 +// int row = 2; +// for (; row < list.size(); row++) { +// ImportExcelField rowField = list.get(row); +// +// //第一选项未合并单元格 单元格拆分后 第1 2 3列相等 +//// if (!rowField.getCellFirst().equals(rowField.getCellSecond()) || !rowField.getCellFirst().equals(rowField.getCellThird()) ){ +//// throw new NflgBusinessException(STATE.Error,StrUtil.format("第{}行,请保持相同格式,{} 未合并单元格 ",rowField.getLineNo(),rowField.getCellFirst())); +//// } +// +// //相同列为根选项(黄色背景) +// if ((row == list.size() - 1) || (rowField.getCellFirst().equals(rowField.getCellSecond()) +// && StrUtil.isEmpty(rowField.getCellThird()))) { +// +// +// if ((row == list.size() - 1)) { +// classList.add(rowField); +// } +// +// name = rowField.getCellFirst(); +// if (CollectionUtil.isNotEmpty(classList)) { +// String finalName = name; +// //黄色根部选项解析 +// int optionParentPos = finalName.indexOf(" "); +// +// OptionalEbomImportDTO optionalEbomImportL1 = new OptionalEbomImportDTO(); +// optionalEbomImportL1.setOptionDrawingNo(StrUtil.sub(finalName, 0, optionParentPos)); +// optionalEbomImportL1.setOptionName(StrUtil.subSuf(finalName, optionParentPos + 1)); +// +// if (CollectionUtil.isEmpty(optionalEbomInportExcelDTO.getOptionInfo())) { +// optionalEbomInportExcelDTO.setOptionInfo(new ArrayList()); +// } +// optionalEbomInportExcelDTO.getOptionInfo().add(optionalEbomImportL1); +// +// Map> group1 = classList.parallelStream() +// .collect(Collectors.groupingBy(ImportExcelField::getCellFirst, LinkedHashMap::new, Collectors.toList())); +// +// if (group1 == null || CollectionUtil.isEmpty(group1)) { +// throw new NflgBusinessException(STATE.Error, StrUtil.format("转换{}选项下数据异常", name)); +// } +// +// parsecColumn2(group1, optionalEbomImportL1); +// +// classList.clear(); +// +// } +// if ((row != list.size() - 1)) { +// name = rowField.getCellFirst(); +// if (StrUtil.isEmpty(name)) { +// throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,选项数据不能为空", rowField.getLineNo())); +// } +// +// if (!name.contains(" ")) { +// throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,格式错误,选项使用空格分隔名称和图号", rowField.getLineNo())); +// } +// +// } +// +// } else { +// classList.add(rowField); +// } +// } +// //最后一项处理 +// return optionalEbomInportExcelDTO; +// +// } + + + OptionalEbomImportExcelDTO parseOptionColumn(List list) { + + OptionalEbomImportExcelDTO optionalEbomInportExcelDTO = new OptionalEbomImportExcelDTO(); - + //第一行设备信息 ImportExcelField device = list.get(0); + optionalEbomInportExcelDTO.setDeviceInfo(parseDevcieInfo(device)); - if(StrUtil.isEmpty(device.getCellFirst())){ - throw new NflgBusinessException(STATE.Error,"机型数据不能为空"); - } - String deviceInfo = device.getCellFirst(); - int deviceSplitPos=deviceInfo.indexOf(" "); - //设备信息 - if(deviceSplitPos<0 ){ - throw new NflgBusinessException(STATE.Error,"第1行,机型设备型号格式异常,使用空格分隔设备编号和名称"); - } - - optionalEbomInportExcelDTO.setDeviceInfo(new OptionalEbomMainDTO()); - optionalEbomInportExcelDTO.getDeviceInfo().setDeviceNo(StrUtil.sub(deviceInfo,0 ,deviceSplitPos )); - - optionalEbomInportExcelDTO.getDeviceInfo().setDeviceName(StrUtil.subSuf(deviceInfo, deviceSplitPos+1 )); - - if(StrUtil.isEmpty( optionalEbomInportExcelDTO.getDeviceInfo().getDeviceName())){ - throw new NflgBusinessException(STATE.Error,"第1行,格式错误,解析后不包含设备名称"); - } - optionalEbomInportExcelDTO.getDeviceInfo().setDeviceName( optionalEbomInportExcelDTO.getDeviceInfo().getDeviceName() .replace("\n","")); - - String name = ""; + String optionName = ""; //相同类 List classList = new ArrayList<>(); + //跳过 第一行标题 选配内容 标配\可选 int row = 2; for (; row < list.size(); row++) { ImportExcelField rowField = list.get(row); + optionName = rowField.getCellFirst(); + optionName= optionName.replace("\t", " "); - //第一选项未合并单元格 - if (StrUtil.isEmpty(rowField.getCellThird()) && !rowField.getCellFirst().equals(rowField.getCellSecond())){ - throw new NflgBusinessException(STATE.Error,StrUtil.format("第{}行,请保持相同格式,{} 未合并单元格 ",rowField.getLineNo(),rowField.getCellFirst())); + + //黄色根部选项解析 + int optionParentPos = optionName.indexOf(" "); + if (optionParentPos<0) { + throw new NflgBusinessException(STATE.Error, StrUtil.format("第{}行,格式错误,选项{}使用空格分隔图号和名称", rowField.getLineNo(), optionName)); + } + OptionalEbomImportDTO optionalEbomImportL1 = new OptionalEbomImportDTO(); + optionalEbomImportL1.setOptionDrawingNo(StrUtil.sub(optionName, 0, optionParentPos).trim()); + optionalEbomImportL1.setOptionName(StrUtil.subSuf(optionName, optionParentPos + 1)); + + if (CollectionUtil.isEmpty(optionalEbomInportExcelDTO.getOptionInfo())) { + optionalEbomInportExcelDTO.setOptionInfo(new ArrayList()); + } + optionalEbomInportExcelDTO.getOptionInfo().add(optionalEbomImportL1); + + while (++row()); - } - optionalEbomInportExcelDTO.getOptionInfo().add(optionalEbomImportL1); - - Map > group1 = classList.parallelStream() - .collect(Collectors.groupingBy(ImportExcelField::getCellFirst,LinkedHashMap::new,Collectors.toList())); - - if(group1==null || CollectionUtil.isEmpty(group1)){ - throw new NflgBusinessException(STATE.Error,StrUtil.format("转换{}选项下数据异常",name)); - } - - parsecColumn2(group1, optionalEbomImportL1); - - classList.clear(); - - } - if((row!=list.size()-1)) { - name = rowField.getCellFirst(); - if(StrUtil.isEmpty(name)){ - throw new NflgBusinessException(STATE.Error,StrUtil.format("第{}行,选项数据不能为空",rowField.getLineNo())); - } - - if(!name.contains(" ")){ - throw new NflgBusinessException(STATE.Error,StrUtil.format("第{}行,格式错误,选项使用空格分隔名称和图号",rowField.getLineNo())); - } - - } - - } else { - classList.add(rowField); + Map> group1 = classList.parallelStream() + .collect(Collectors.groupingBy(ImportExcelField::getCellFirst, LinkedHashMap::new, Collectors.toList())); + if (group1 == null || CollectionUtil.isEmpty(group1)) { + throw new NflgBusinessException(STATE.Error, StrUtil.format("转换{}选项下数据异常", optionName)); } + parseOptionColumn2(group1, optionalEbomImportL1); + classList.clear(); + + } - //最后一项处理 - - - - return optionalEbomInportExcelDTO; + } + + + /** + * 解析设备 + * + * @param device + * @return + */ + OptionalEbomMainDTO parseDevcieInfo(ImportExcelField device) { + if (StrUtil.isEmpty(device.getCellFirst())) { + throw new NflgBusinessException(STATE.Error, "机型数据不能为空"); + } + String deviceInfo = device.getCellFirst(); + int deviceSplitPos = deviceInfo.indexOf(" "); + + //设备信息 + if (deviceSplitPos < 0) { + throw new NflgBusinessException(STATE.Error, "第1行,机型设备型号格式异常,使用空格分隔设备编号和名称"); + } + OptionalEbomMainDTO deviceDto = new OptionalEbomMainDTO(); + deviceDto.setDeviceNo(StrUtil.sub(deviceInfo, 0, deviceSplitPos)); + deviceDto.setDeviceName(StrUtil.subSuf(deviceInfo, deviceSplitPos + 1)); + + if (StrUtil.isEmpty(deviceDto.getDeviceNo())) { + throw new NflgBusinessException(STATE.Error, "第1行,格式错误,解析后不包含设备编码"); + } + if (StrUtil.isEmpty(deviceDto.getDeviceName())) { + throw new NflgBusinessException(STATE.Error, "第1行,格式错误,解析后不包含设备名称"); + } + + deviceDto.setDeviceName(deviceDto.getDeviceName().replace("\n", "")); + + return deviceDto; } public Boolean importExcel(InputStream inputStream) throws NflgBusinessException { if (inputStream == null) { - new NflgBusinessException(STATE.Error, "文件流内容空"); + throw new NflgBusinessException(STATE.Error, "文件流内容空"); } //解析excel ImportExcelHelper helper = new ImportExcelHelper<>(); List list = helper.getList(inputStream, ImportExcelField.class, 0, 0); OptionalEbomImportExcelDTO optionalEbomInportExcelDTO = null; if (CollectionUtil.isNotEmpty(list)) { - optionalEbomInportExcelDTO = parsecColumn1(list); + optionalEbomInportExcelDTO = parseOptionColumn(list); } - if (optionalEbomInportExcelDTO != null) { - optionalEbomInportExcelDTO.getOptionInfo().forEach(item -> { - List listParent = item.getChild(); - for (OptionalEbomImportDTO item1 : - listParent) { - List listChild = item1.getChild(); - - // - SpringUtil.getBean(MaterialMainService.class).initMaterialForDrawdingNoImmul(listChild, OptionalEbomImportChildDTO::getDrawingNo, OptionalEbomImportChildDTO::setMaterialNo, OptionalEbomImportChildDTO::setMaterialDesc); - - for (OptionalEbomImportChildDTO childDTO : listChild) { - if (!childDTO.getTag() && StringUtils.isEmpty(childDTO.getMaterialNo())) { - //in 批量没匹配到 再模糊匹配一次 - List likeList= SpringUtil.getBean(MaterialMainService.class) - .getMaterialLikeByDrawingNo(StrUtil.format("{} {}",childDTO.getDrawingNo(),childDTO.getMaterialName())); - if(CollectionUtil.isNotEmpty(likeList) ) { - if (likeList.size() == 1) { - BaseMaterialVO materialVO = likeList.get(0); - childDTO.setMaterialNo(materialVO.getMaterialNo()); - childDTO.setMaterialDesc(materialVO.getMaterialDesc()); - continue; - } else if (likeList.size() > 1) { - throw new NflgBusinessException(STATE.BusinessError, StrUtil.format("第{}行,{} 图号匹配到多条物料数据", childDTO.getLineNo(), childDTO.getDrawingNo())); - } - - } - - // childDTO.setMaterialNo(childDTO.getDrawingNo()); - childDTO.setError(childDTO.getError() | OptionalBomConstant.ExcelErrorTagEnum.MATERIA_NO_UNKOWN.getValue()); - item1.setError(true); - } - } - - - } - }); - - + if(optionalEbomInportExcelDTO==null){ + throw new NflgBusinessException(STATE.Error, "解析数据失败"); } +// if (optionalEbomInportExcelDTO != null) { +// for( OptionalEbomImportDTO item:optionalEbomInportExcelDTO.getOptionInfo()) { +// List listParent = item.getChild(); +// for (OptionalEbomImportDTO item1 : +// listParent) { +// List listChild = item1.getChild(); +// // +// // SpringUtil.getBean(MaterialMainService.class).initMaterialForDrawdingNoImmul(listChild, OptionalEbomImportChildDTO::getDrawingNo, OptionalEbomImportChildDTO::setMaterialNo, OptionalEbomImportChildDTO::setMaterialDesc); +// +// SpringUtil.getBean(MaterialMainService.class).intiMaterialInfo(listChild,OptionalEbomImportChildDTO::getMaterialNo); +// for (OptionalEbomImportChildDTO childDTO : listChild) { +// //!childDTO.getTag() && +// if (StringUtils.isEmpty(childDTO.getDrawingNo())) { +// childDTO.setError(childDTO.getError() | OptionalBomConstant.ExcelErrorTagEnum.MATERIA_NO_UNKOWN.getValue()); +// item1.setError(true); +// } +// } +// } +// } +// } + //检查是否满足条件 除了‘无’ ,物料号不能为空 String hintMsg = isValiData(optionalEbomInportExcelDTO.getOptionInfo()); if (StrUtil.isNotEmpty(hintMsg)) { throw new NflgBusinessException(STATE.Error, hintMsg); } - System.out.println(JSON.toJSONString(optionalEbomInportExcelDTO)); - // return true; + System.out.println(JSON.toJSONString(optionalEbomInportExcelDTO)); + // return true; //保存db - return batchExcelToRepertory(optionalEbomInportExcelDTO); + return batchExcelToRepertory(optionalEbomInportExcelDTO); } @@ -348,8 +507,6 @@ public class OptionalExcelService { excelList.forEach(item -> { List listParent = item.getChild(); for (OptionalEbomImportDTO item1 : listParent) { - if (item1.isError()) { - List listChild = item1.getChild(); for (OptionalEbomImportChildDTO item2 : listChild) { if (item2.getError() == OptionalBomConstant.ExcelErrorTagEnum.REPEAT.getValue()) { @@ -360,9 +517,6 @@ public class OptionalExcelService { title.append(String.format("第%d行 %s ,", item2.getLineNo(), OptionalBomConstant.ExcelErrorTagEnum.ALL.getDescription())); } - } - - } } }); @@ -371,7 +525,7 @@ public class OptionalExcelService { } - // @Transactional(rollbackFor = Exception.class) + // @Transactional(rollbackFor = Exception.class) public Boolean batchExcelToRepertory(OptionalEbomImportExcelDTO ebomImportExcelDTO) { OptionalEbomMainEntity optionalEbomMainEntity = Convert.convert(new TypeReference() { @@ -396,10 +550,10 @@ public class OptionalExcelService { optionalEbomMainService.save(optionalEbomMainEntity); - }else{ - optionalEbomMainEntity=queryDevice; + } else { + optionalEbomMainEntity = queryDevice; - } + } if (optionalEbomMainEntity == null || optionalEbomMainEntity.getRowId() == null) { throw new NflgBusinessException(STATE.Error, "保存设备数据失败"); @@ -409,7 +563,7 @@ public class OptionalExcelService { List parentOptionList = ebomImportExcelDTO.getOptionInfo(); - ConvertToMainHistory convertToMainHistory=new ConvertToMainHistory(); + ConvertToMainHistory convertToMainHistory = new ConvertToMainHistory(); convertToMainHistory.convertToMainHistory(optionalEbomMainEntity.getRowId()); //保存选项 @@ -425,7 +579,7 @@ public class OptionalExcelService { parentOptionEntity = Convert.convert(new TypeReference() { }, parentOption); parentOptionEntity.setRootRowId(optionalEbomMainEntity.getRowId()); - parentOptionEntity.setCreatedTime(DateUtil.now()); + parentOptionEntity.setCreatedTime(DateUtil.now()); parentOptionEntity.setCreatedBy(SessionUtil.getUserCode()); optionalEbomImportService.save(parentOptionEntity); } @@ -437,8 +591,6 @@ public class OptionalExcelService { List childOptionList = parentOption.getChild(); - - for (OptionalEbomImportDTO childOption : childOptionList) { QueryWrapper queryWrapper2 = new QueryWrapper<>(); @@ -453,7 +605,7 @@ public class OptionalExcelService { childOptionEntity.setRootRowId(optionalEbomMainEntity.getRowId()); childOptionEntity.setParentRowId(parentOptionEntity.getRowId()); - childOptionEntity.setCreatedTime(DateUtil.now()); + childOptionEntity.setCreatedTime(DateUtil.now()); optionalEbomImportService.save(childOptionEntity); } // else{ @@ -494,8 +646,8 @@ public class OptionalExcelService { } //首次添加设备不用操作保存历史记录 - if(queryDevice!=null){ - SpringUtil.getBean(OptionalEbomMainHistoryService.class).convertToHistory(convertToMainHistory,true); + if (queryDevice != null) { + SpringUtil.getBean(OptionalEbomMainHistoryService.class).convertToHistory(convertToMainHistory, true); } return true; diff --git a/nflg_project_dev/nflg-bom-new/src/main/resources/template/importDataTemplate.xlsx b/nflg_project_dev/nflg-bom-new/src/main/resources/template/importDataTemplate.xlsx index b956028ae3faf5a6754b43533dc75e37ef0b431d..1fab073db6bd28c2655c928036f09680fd155625 100644 GIT binary patch delta 11040 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%0D$(6Jf3#!u5Mm- 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