feat(excel): 优化Excel导入功能支持动态工作表查找

- 添加findSheetIndex方法支持根据工作表名称查找索引
- 实现精确匹配、前缀匹配和包含匹配的查找逻辑
- 在各个控制器中使用动态工作表索引替换固定索引
- 优化CreditCompanyController中的必填字段验证逻辑
- 移除对code字段的必填验证要求
- 添加工作表名称标准化处理功能
This commit is contained in:
2026-01-08 18:16:44 +08:00
parent abbcd992a4
commit 3434f4d8e6
6 changed files with 58 additions and 10 deletions

View File

@@ -197,14 +197,14 @@ public class CreditCompanyController extends BaseController {
}
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
// 验证必填字段
if (item.getName() == null || item.getName().trim().isEmpty()) {
if (item.getMatchName() == null || item.getMatchName().trim().isEmpty()) {
errorMessages.add("" + excelRowNumber + "行:项目名称不能为空");
continue;
}
if (item.getCode() == null || item.getCode().trim().isEmpty()) {
errorMessages.add("" + excelRowNumber + "行:唯一标识不能为空");
continue;
}
// if (item.getCode() == null || item.getCode().trim().isEmpty()) {
// errorMessages.add("第" + excelRowNumber + "行:唯一标识不能为空");
// continue;
// }
boolean saved = creditCompanyService.save(item);
if (!saved) {

View File

@@ -141,8 +141,9 @@ public class CreditCompetitorController extends BaseController {
int successCount = 0;
try {
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "竞争对手", 2);
ExcelImportSupport.ImportResult<CreditCompetitorImportParam> importResult = ExcelImportSupport.read(
file, CreditCompetitorImportParam.class, this::isEmptyImportRow,2);
file, CreditCompetitorImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditCompetitorImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();

View File

@@ -141,8 +141,9 @@ public class CreditExternalController extends BaseController {
int successCount = 0;
try {
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "对外投资", 0);
ExcelImportSupport.ImportResult<CreditExternalImportParam> importResult = ExcelImportSupport.read(
file, CreditExternalImportParam.class, this::isEmptyImportRow);
file, CreditExternalImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditExternalImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();

View File

@@ -141,9 +141,9 @@ public class CreditRiskRelationController extends BaseController {
int successCount = 0;
try {
// 风险关系数据位于第二个选项卡sheetIndex = 1
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "风险关系", 1);
ExcelImportSupport.ImportResult<CreditRiskRelationImportParam> importResult = ExcelImportSupport.read(
file, CreditRiskRelationImportParam.class, this::isEmptyImportRow, 1);
file, CreditRiskRelationImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditRiskRelationImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();

View File

@@ -141,8 +141,9 @@ public class CreditSupplierController extends BaseController {
int successCount = 0;
try {
int sheetIndex = ExcelImportSupport.findSheetIndex(file, "供应商", 3);
ExcelImportSupport.ImportResult<CreditSupplierImportParam> importResult = ExcelImportSupport.read(
file, CreditSupplierImportParam.class, this::isEmptyImportRow,3);
file, CreditSupplierImportParam.class, this::isEmptyImportRow, sheetIndex);
List<CreditSupplierImportParam> list = importResult.getData();
int usedTitleRows = importResult.getTitleRows();
int usedHeadRows = importResult.getHeadRows();

View File

@@ -20,6 +20,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Predicate;
/**
@@ -192,6 +193,50 @@ public class ExcelImportSupport {
}
}
/**
* 根据 sheet 名称查找下标(优先精确匹配,其次前缀匹配/包含匹配)。
*
* @return 找不到返回 -1
*/
public static int findSheetIndex(MultipartFile file, String sheetName) throws Exception {
if (file == null || sheetName == null || sheetName.trim().isEmpty()) {
return -1;
}
String target = normalizeSheetName(sheetName);
if (target.isEmpty()) {
return -1;
}
try (InputStream is = file.getInputStream(); Workbook workbook = WorkbookFactory.create(is)) {
int sheetCount = workbook.getNumberOfSheets();
for (int i = 0; i < sheetCount; i++) {
String candidate = normalizeSheetName(workbook.getSheetName(i));
if (Objects.equals(candidate, target)) {
return i;
}
}
for (int i = 0; i < sheetCount; i++) {
String candidate = normalizeSheetName(workbook.getSheetName(i));
if (candidate.startsWith(target) || candidate.contains(target) || target.startsWith(candidate)) {
return i;
}
}
return -1;
}
}
public static int findSheetIndex(MultipartFile file, String sheetName, int defaultIndex) throws Exception {
int idx = findSheetIndex(file, sheetName);
return idx >= 0 ? idx : defaultIndex;
}
private static String normalizeSheetName(String sheetName) {
if (sheetName == null) {
return "";
}
return sheetName.replace(" ", "").replace(" ", "").trim();
}
/**
* 读取指定列(由表头名定位)的超链接,返回:单元格显示值 -> 超链接地址。
*