| | |
| | | } |
| | | } |
| | | |
| | | /** 按表头关键字定位列号:从第 1 列向右扫,命中任一关键字即返回该列;未命中返回 -1 */ |
| | | private int findColByKeywords(Row header, String... keywords) { |
| | | if (header == null) return -1; |
| | | for (int c = 0; c <= header.getLastCellNum(); c++) { |
| | | Cell cell = header.getCell(c); |
| | | if (cell == null) continue; |
| | | String h = FORMATTER.formatCellValue(cell).trim(); |
| | | if (h.isEmpty()) continue; |
| | | for (String k : keywords) { |
| | | if (h.contains(k)) return c; |
| | | } |
| | | } |
| | | return -1; |
| | | } |
| | | |
| | | /** 表头行文本(报错提示用),最多取 12 列 */ |
| | | private String headerText(Row header) { |
| | | if (header == null) return "空"; |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (int c = 0; c < Math.min(header.getLastCellNum(), 12); c++) { |
| | | Cell cell = header.getCell(c); |
| | | String h = cell == null ? "" : FORMATTER.formatCellValue(cell).trim(); |
| | | if (h.isEmpty()) continue; |
| | | if (sb.length() > 0) sb.append(" | "); |
| | | sb.append(h); |
| | | } |
| | | return sb.length() == 0 ? "空" : sb.toString(); |
| | | } |
| | | |
| | | /** 按表头名称建立列号映射,兼容新旧模板列位差异 */ |
| | | private Map<String, Integer> buildHeaderMap(Row header) { |
| | | Map<String, Integer> colMap = new HashMap<>(); |
| | |
| | | this.monthly = monthly; |
| | | } |
| | | } |
| | | /** 投资系统导出导入(审核比对基准),固定8列:行号/单位/时期/计划总投资/自开始累计/本年计划/自年初累计/当月完成 */ |
| | | private static final int[] INVEST_SYSTEM_HEADER_COLS = {0, 1, 2, 3, 4, 5, 6, 7}; |
| | | private static final String[] INVEST_SYSTEM_HEADER_KEYWORDS = |
| | | {"行号", "单位", "时期", "计划总投资", "自开始建设", "本年计划投资", "自年初", "当月完成投资"}; |
| | | |
| | | /** 投资系统导出导入(审核比对基准)。 |
| | | * 列位**按表头关键字定位**,兼容两种模板: |
| | | * - 老模板《模板_查询结果(投资系统-客运+物流 2026.7).xls》:行号/单位/时期/计划总投资/自开始建设累计/本年计划投资/自年初累计/当月完成投资 |
| | | * - 新模板《2026年X月投资系统项目明细.xls》(用户 2026-09-21 更换):行号/投资项目/时期/项目所处阶段/计划总投资/本年计划投资/自开始建设至本年(月)底-累计完成投资/当月完成投资 |
| | | * 新模板**没有「自年初累计」列** → year_cum 留空(审核时按「基准缺失」跳过,不再当成 0 参与比对)。 */ |
| | | public int importInvestmentSystem(MultipartFile file, String period) throws Exception { |
| | | List<InvestmentSystem> list = new ArrayList<>(); |
| | | int failRows = 0; |
| | | try (Workbook wb = WorkbookFactory.create(file.getInputStream())) { |
| | | Sheet sheet = wb.getSheetAt(0); |
| | | requireHeaderKeyword(sheet, "投资系统导出", "项目名称", "计划总投资", "单位"); |
| | | requireHeaderLayout(sheet, "投资系统导出", "模板_查询结果(投资系统-客运+物流 2026.7).xls", |
| | | INVEST_SYSTEM_HEADER_COLS, INVEST_SYSTEM_HEADER_KEYWORDS); |
| | | requireHeaderKeyword(sheet, "投资系统导出", "投资项目", "项目名称", "单位", "计划总投资"); |
| | | Row header = sheet.getRow(0); |
| | | int cName = findColByKeywords(header, "投资项目", "项目名称", "单位"); |
| | | int cTotal = findColByKeywords(header, "计划总投资"); |
| | | int cYearPlan = findColByKeywords(header, "本年计划投资"); |
| | | int cStartCum = findColByKeywords(header, "自开始建设"); |
| | | int cYearCum = findColByKeywords(header, "自年初"); |
| | | int cMonthDone = findColByKeywords(header, "当月完成投资"); |
| | | if (cName < 0 || cTotal < 0 || cYearPlan < 0 || cStartCum < 0 || cMonthDone < 0) { |
| | | throw new RuntimeException("所选数据类型【投资系统导出】表头列不完整:需要「投资项目(或单位)、计划总投资、本年计划投资、" |
| | | + "自开始建设…累计完成投资、当月完成投资」等列,实际表头为「" + headerText(header) |
| | | + "」。请使用系统模板《2026年X月投资系统项目明细》或《模板_查询结果(投资系统-客运+物流)》整理后再导入"); |
| | | } |
| | | for (int r = 1; r <= sheet.getLastRowNum(); r++) { |
| | | Row row = sheet.getRow(r); |
| | | if (row == null) continue; |
| | | String name = getString(row, 1); |
| | | String name = getString(row, cName); |
| | | if (name == null || name.trim().isEmpty()) continue; |
| | | InvestmentSystem sys = new InvestmentSystem(); |
| | | sys.setReportPeriod(period); |
| | | sys.setProjectName(name.trim()); |
| | | sys.setTotalInvestment(getDecimal(row, 3)); |
| | | sys.setStartCum(getDecimal(row, 4)); |
| | | sys.setYearPlan(getDecimal(row, 5)); |
| | | sys.setYearCum(getDecimal(row, 6)); |
| | | sys.setMonthDone(getDecimal(row, 7)); |
| | | sys.setTotalInvestment(getDecimal(row, cTotal)); |
| | | sys.setStartCum(getDecimal(row, cStartCum)); |
| | | sys.setYearPlan(getDecimal(row, cYearPlan)); |
| | | sys.setYearCum(cYearCum < 0 ? null : getDecimal(row, cYearCum)); |
| | | sys.setMonthDone(getDecimal(row, cMonthDone)); |
| | | list.add(sys); |
| | | } |
| | | } catch (Exception e) { |