fix(wms):入库单导入表头字段错位、备注丢失
- 取值向右查找时误把下一个标签/选项说明当值(承运方←Tel:、生产商←客户名称:、监管方式←送货地址:、送货地址←查验选项),现遇疑似标签即停止查找 - 备注:xxx同格书写为全角冒号,原仅按半角:拆分导致备注丢失,现全角/半角兼容 - 表头列遍历上界改用getLastCellNum,防空单元格漏扫尾部列"
This commit is contained in:
+59
-21
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user