From d22c05a9f7bbb4cbc800d2b2bccc0da2dc5faed7 Mon Sep 17 00:00:00 2001 From: "han\\hanst" Date: Mon, 1 Dec 2025 11:38:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=A8=E9=83=A8=E5=88=97=E9=83=BD=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E8=8E=B7=E5=8F=96=E7=BC=93=E5=AD=98=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ecss/service/impl/CoDelServiceImpl.java | 156 ++++++++++++++---- 1 file changed, 122 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelServiceImpl.java b/src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelServiceImpl.java index 0c1f58b2..6dd20fcf 100644 --- a/src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelServiceImpl.java +++ b/src/main/java/com/xujie/sys/modules/ecss/service/impl/CoDelServiceImpl.java @@ -344,6 +344,30 @@ public class CoDelServiceImpl implements CoDelService { return getNumericCellValueOrDefault(row, columnIndex); } + /** + * 判断单元格值是否有效 + * 无效值包括:空值、"0"、Excel错误(#REF!、#N/A、#VALUE!等) + * + * @param cellValue 单元格字符串值 + * @return true=有效值,false=无效值 + */ + private boolean isValidCellValue(String cellValue) { + // 1. 空值或空字符串 + if (StringUtils.isBlank(cellValue)) { + return false; + } + + // 2. 值为"0" + if ("0".equals(cellValue.trim())) { + return false; + } + + // 3. Excel错误值(以#开头,如#REF!、#N/A、#VALUE!、#DIV/0!、#NAME?、#NUM!、#NULL!等) + return !cellValue.trim().startsWith("#"); + + // 其他情况视为有效值 + } + /** * 解析Excel第一行,建立列名到列索引的映射关系 * @@ -409,18 +433,21 @@ public class CoDelServiceImpl implements CoDelService { // 获取第三行(表头行) XSSFRow headerRow = sheet.getRow(2); - - // 验证第一列第3行必须是"PO Rec. Date"且不能为空 - if (headerRow == null || headerRow.getCell(0) == null - || StringUtils.isBlank(getStringCellValue(headerRow, 0)) - || !getStringCellValue(headerRow, 0).trim().equals("PO Rec. Date")) { - log.warn("Sheet {} 的第一列第3行不是 'PO Rec. Date' 或为空,跳过该Sheet", sheet.getSheetName()); - continue; // 跳过该Sheet + if (headerRow == null) { + log.warn("Sheet {} 的第3行为空,跳过该Sheet", sheet.getSheetName()); + continue; } // 解析表头行(第3行),获取列索引映射 Map columnMap = parseExcelHeader(headerRow); + // 获取Cargo Ready Date列索引 + Integer cargoReadyDateIdx = columnMap.get("Cargo Ready Date"); + if (cargoReadyDateIdx == null) { + log.warn("Sheet {} 中未找到 'Cargo Ready Date' 列,跳过该Sheet", sheet.getSheetName()); + continue; + } + // 遍历每一行(从第四行开始,即索引3) for (int j = 3; j < rows; j++) { // 获得该行 @@ -429,10 +456,11 @@ public class CoDelServiceImpl implements CoDelService { continue; } - // 检查第一列,如果没有值或者值是空字符串则跳过该行 - if (row.getCell(0).getCellType() == CellType.BLANK || row.getCell(0).getCellType() == CellType.ERROR - || row.getCell(0) == null || StringUtils.isBlank(getStringCellValue(row, 0))) { - log.debug("第{}行第一列为空,跳过该行", j+1); + // 检查Cargo Ready Date列,如果没有值则跳过该行 + if (row.getCell(cargoReadyDateIdx) == null + || row.getCell(cargoReadyDateIdx).getCellType() == CellType.BLANK + || row.getCell(cargoReadyDateIdx).getCellType() == CellType.ERROR) { + log.debug("第{}行的Cargo Ready Date列为空,跳过该行", j+1); continue; } @@ -443,11 +471,7 @@ public class CoDelServiceImpl implements CoDelService { continue; } - // 必填字段验证 - Integer cargoReadyDateIdx = columnMap.get("Cargo Ready Date"); - if (row.getCell(cargoReadyDateIdx) == null) { - throw new RuntimeException("第" + (j+1) + "行的Cargo Ready Date不能为空!"); - } + // 必填字段验证 - Cargo Ready Date已经在上面检查过了 Integer poIdx = columnMap.get("PO#"); if (row.getCell(poIdx) == null) { @@ -495,7 +519,7 @@ public class CoDelServiceImpl implements CoDelService { LocalDate localDate = parseDateCell(row.getCell(cargoReadyDateIdx)); String formatted = localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); readDate = DateUtils.getDateByParten(formatted, "yyyy-MM-dd"); - } catch (ParseException e) { + } catch (Exception e) { throw new RuntimeException("第" + (j+1) + "行的ReadyDate格式有误!"); } task.setReadyDate(readDate); @@ -509,16 +533,20 @@ public class CoDelServiceImpl implements CoDelService { task.setCurrency(getStringCellValue(row, currencyIdx)); task.setTp(getNumericCellValueOrDefault(row, tpIdx)); - // 处理CMC Invoice:如果CMC Invoice为空则取Shipping Number,如果两者都为空则报错 + // 处理CMC Invoice:如果CMC Invoice为空/0/Excel错误则取Shipping Number,如果两者都为空则报错 String cmcInvoiceValue = getStringCellValueSafe(row, columnMap, "CMC Invoice"); String shippingNumberValue = getStringCellValueSafe(row, columnMap, "Shipping Number"); - if (StringUtils.isBlank(cmcInvoiceValue) && StringUtils.isBlank(shippingNumberValue)) { + // 判断CMC Invoice是否为有效值(排除空值、"0"、Excel错误) + boolean isCmcInvoiceValid = isValidCellValue(cmcInvoiceValue); + boolean isShippingNumberValid = isValidCellValue(shippingNumberValue); + + if (!isCmcInvoiceValid && !isShippingNumberValid) { throw new RuntimeException("第" + (j+1) + "行的CMC Invoice和Shipping Number不能同时为空!"); } - // 如果CMC Invoice为空,则使用Shipping Number - if (StringUtils.isBlank(cmcInvoiceValue)) { + // 如果CMC Invoice无效(空/0/错误),则使用Shipping Number + if (!isCmcInvoiceValid) { task.setCmcInvoice(shippingNumberValue); } else { task.setCmcInvoice(cmcInvoiceValue); @@ -581,11 +609,11 @@ public class CoDelServiceImpl implements CoDelService { try { CellType cellType = cell.getCellType(); - + // 处理数值类型(日期格式) if (cellType == CellType.NUMERIC && DateUtil.isCellDateFormatted(cell)) { return cell.getDateCellValue().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); - } + } // 处理字符串类型 else if (cellType == CellType.STRING) { String val = cell.getStringCellValue().trim(); @@ -705,6 +733,41 @@ public class CoDelServiceImpl implements CoDelService { if (cell == null || cell.getCellType() == CellType.BLANK) { return ""; } + + CellType cellType = cell.getCellType(); + + // 处理公式类型 - 获取缓存结果 + if (cellType == CellType.FORMULA) { + switch (cell.getCachedFormulaResultType()) { + case NUMERIC: + // 公式结果是数值类型 - 直接获取数值并转换为字符串 + // 检查是否是日期格式 + if (DateUtil.isCellDateFormatted(cell)) { + DataFormatter formatter = new DataFormatter(); + return formatter.formatCellValue(cell); + } else { + // 普通数值,转换为字符串(去除小数点后的零) + double numericValue = cell.getNumericCellValue(); + // 如果是整数,去掉.0 + if (numericValue == Math.floor(numericValue)) { + return String.valueOf((long) numericValue); + } else { + return String.valueOf(numericValue); + } + } + case STRING: + // 公式结果是字符串类型 + return cell.getStringCellValue(); + case BLANK: + return ""; + case BOOLEAN: + return String.valueOf(cell.getBooleanCellValue()); + default: + return ""; + } + } + + // 处理其他类型使用DataFormatter统一格式化 DataFormatter formatter = new DataFormatter(); return formatter.formatCellValue(cell); } @@ -714,19 +777,41 @@ public class CoDelServiceImpl implements CoDelService { if (cell == null || cell.getCellType() == CellType.BLANK) { return null; } - DataFormatter formatter = new DataFormatter(); - String cellValueAsString = formatter.formatCellValue(cell); - try { - // 尝试将字符串转换为整数 - return Integer.parseInt(cellValueAsString); - } catch (NumberFormatException e) { - // 如果转换失败,尝试将数字值四舍五入到最接近的整数 - if (cell.getCellType() == CellType.NUMERIC) { - return (int) Math.round(cell.getNumericCellValue()); + + CellType cellType = cell.getCellType(); + + // 处理数值类型 + if (cellType == CellType.NUMERIC) { + return (int) Math.round(cell.getNumericCellValue()); + } + + // 处理字符串类型 + if (cellType == CellType.STRING) { + try { + return Integer.parseInt(cell.getStringCellValue().trim()); + } catch (NumberFormatException e) { + return -1; + } + } + + // 处理公式类型 - 获取缓存结果 + if (cellType == CellType.FORMULA) { + switch (cell.getCachedFormulaResultType()) { + case NUMERIC: + return (int) Math.round(cell.getNumericCellValue()); + case STRING: + try { + return Integer.parseInt(cell.getStringCellValue().trim()); + } catch (NumberFormatException e) { + return -1; + } + default: + return -1; } - // 如果单元格既不是数字也不是可解析的字符串,则返回-1 - return -1; } + + // 其他类型返回-1 + return -1; } private BigDecimal getNumericCellValueOrDefault(XSSFRow row, int columnIndex) { @@ -753,6 +838,9 @@ public class CoDelServiceImpl implements CoDelService { return formulaValue.setScale(6, RoundingMode.HALF_UP); // 四舍五入保留四位小数 case STRING: try { + if (cell.getStringCellValue() == null || cell.getStringCellValue().isEmpty()) { + return null; + } BigDecimal stringValue = new BigDecimal(cell.getStringCellValue()); return stringValue.setScale(6, RoundingMode.HALF_UP); // 四舍五入保留四位小数 } catch (NumberFormatException e) {