From cc943d164bd879502e89616a99f78757b4a35b4d Mon Sep 17 00:00:00 2001 From: rcx <3084692334@qq.com> Date: Thu, 20 Aug 2026 10:06:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(wms):=E5=85=A5=E5=BA=93=E5=8D=95=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E8=A1=A8=E5=A4=B4=E5=AD=97=E6=AE=B5=E9=94=99=E4=BD=8D?= =?UTF-8?q?=E3=80=81=E5=A4=87=E6=B3=A8=E4=B8=A2=E5=A4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 取值向右查找时误把下一个标签/选项说明当值(承运方←Tel:、生产商←客户名称:、监管方式←送货地址:、送货地址←查验选项),现遇疑似标签即停止查找 - 备注:xxx同格书写为全角冒号,原仅按半角:拆分导致备注丢失,现全角/半角兼容 - 表头列遍历上界改用getLastCellNum,防空单元格漏扫尾部列" --- .../StockInOrderApplicationService.java | 80 ++++++++++++++----- 1 file changed, 59 insertions(+), 21 deletions(-) diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java index 99e6dc2b8..4a581fc00 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java @@ -1000,7 +1000,7 @@ public class StockInOrderApplicationService { for (int rowIdx = 0; rowIdx < 12; rowIdx++) { Row row = sheet.getRow(rowIdx); if (row != null) { - for (int colIdx = 0; colIdx < row.getPhysicalNumberOfCells(); colIdx++) { + for (int colIdx = 0; colIdx < row.getLastCellNum(); colIdx++) { Cell labelCell = row.getCell(colIdx); if (labelCell != null) { String labelValue = getCellValueAsString(labelCell); @@ -1009,42 +1009,45 @@ public class StockInOrderApplicationService { log.info("表头第{}行第{}列: {}", rowIdx + 1, colIdx + 1, labelValue); String value = null; - // 先尝试从同一单元格提取值(如果包含冒号) + // 先尝试从同一单元格提取值(兼容全角":"与半角":",如"备注:xxx") String extractedFromSameCell = null; - if (labelValue.contains(":")) { - String[] parts = labelValue.split(":", 2); - if (parts.length > 1) { - extractedFromSameCell = parts[1].trim(); + String labelKey = labelValue; + int colonIdx = labelValue.indexOf(":"); + if (colonIdx < 0) { + colonIdx = labelValue.indexOf(":"); + } + if (colonIdx >= 0) { + labelKey = labelValue.substring(0, colonIdx).trim(); + String afterColon = labelValue.substring(colonIdx + 1).trim(); + // 选项说明类标签(如"车型及车牌:3T、5T、8T、10T"、"海关是否查验货物:是、否")冒号后是选项说明而非实际值 + if (StringUtils.isNotBlank(afterColon) && !isOptionLabel(labelKey)) { + extractedFromSameCell = afterColon; } } - - // 跳过空单元格,查找下一个非空单元格作为值(最多向后查找10列) + + // 向右查找下一个非空单元格作为值:遇到疑似标签/选项说明(含冒号或命中标签关键词)直接停止, + // 避免把下一个标签(如"承运方:"右侧的"Tel:")或选项说明当成值导致数据错位 String nextCellValue = null; - for (int searchColIdx = colIdx + 1; searchColIdx < colIdx + 10 && searchColIdx < row.getPhysicalNumberOfCells(); searchColIdx++) { + for (int searchColIdx = colIdx + 1; searchColIdx < colIdx + 10 && searchColIdx < row.getLastCellNum(); searchColIdx++) { Cell valueCell = row.getCell(searchColIdx); if (valueCell != null) { String cellValue = getCellValueAsString(valueCell); if (StringUtils.isNotBlank(cellValue)) { + if (looksLikeLabel(cellValue)) { + log.info("表头第{}行,标签'{}'在第{}列,向右第{}列是另一个标签/选项说明'{}',停止查找", rowIdx + 1, labelValue, colIdx + 1, searchColIdx + 1, cellValue); + break; + } nextCellValue = cellValue; log.info("表头第{}行,标签'{}'在第{}列,找到值'{}'在第{}列", rowIdx + 1, labelValue, colIdx + 1, nextCellValue, searchColIdx + 1); break; } } } - - // 优先使用下一个非空单元格的值(如果存在且不为空) - // 如果下一个单元格为空,且同一单元格有冒号后的值,则使用冒号后的值 - // 但如果冒号后的值是选项列表(如"3T、5T、8T、10T"),则应该使用下一个单元格的值 + + // 优先使用右侧紧邻的实际值,其次使用同一单元格冒号后的值 if (StringUtils.isNotBlank(nextCellValue)) { - // 如果冒号后的值是选项列表(包含顿号、逗号等),优先使用下一个单元格的值 - if (extractedFromSameCell != null && (extractedFromSameCell.contains("、") || extractedFromSameCell.contains(","))) { - value = nextCellValue; - } else { - // 否则优先使用下一个单元格的值 - value = nextCellValue; - } + value = nextCellValue; } else if (StringUtils.isNotBlank(extractedFromSameCell)) { - // 如果下一个单元格为空,使用同一单元格冒号后的值 value = extractedFromSameCell; } @@ -2285,6 +2288,41 @@ public class StockInOrderApplicationService { } } + /** + * 判断表头标签(冒号前的部分)是否为选项说明类标签: + * 这类标签冒号后跟的是选项说明(如"车型及车牌:3T、5T、8T、10T"、"海关是否查验货物:是、否")而非实际填写值 + */ + private boolean isOptionLabel(String labelKey) { + if (StringUtils.isBlank(labelKey)) { + return false; + } + return labelKey.contains("车型及车牌") || labelKey.contains("柜号") || labelKey.contains("海关是否查验货物") + || labelKey.contains("是否需要报关") || labelKey.contains("是否需要运输"); + } + + /** + * 判断表头单元格文本是否疑似"标签/选项说明"而非实际值: + * 包含全角":"或半角":"(如"Tel:"、"客户名称:"),或命中常见标签关键词(如无冒号的"起运/运抵国(地区)")。 + * 向右查找标签的值时遇到此类单元格应停止查找,避免把标签文本当成值导致导入数据错位。 + */ + private boolean looksLikeLabel(String cellValue) { + if (StringUtils.isBlank(cellValue)) { + return false; + } + if (cellValue.contains(":") || cellValue.contains(":")) { + return true; + } + String[] labelKeywords = {"委托编号", "客户名称", "联系人", "车型及车牌", "司机签名", "申报地关区", "生产商", + "报关员", "送货地址", "进出境关别", "起运/运抵国", "运抵国", "承运方", "柜号", "运输方式", "监管方式", + "海关是否查验", "入仓日期", "完成时间", "下单日期", "备注", "Tel", "Fax"}; + for (String keyword : labelKeywords) { + if (cellValue.contains(keyword)) { + return true; + } + } + return false; + } + /** * @description 设置仓库信息 * @author ZhouGY