package com.nokia.financeapi.shouqi; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; import com.nokia.financeapi.common.exception.MyRuntimeException; import com.nokia.financeapi.service.car.CarService; import com.nokia.financeapi.service.common.AreaService; import com.nokia.financeapi.service.common.OrganizationService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellValue; import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.FormulaEvaluator; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.io.InputStream; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.stream.Stream; /** * 首汽车辆租赁费加工测试 */ @Slf4j @SpringBootTest @ActiveProfiles("prod") class CarZuLinTests { @Autowired CarService carService; @Autowired OrganizationService organizationService; @Autowired AreaService areaService; @Test void runJobTest() { runJob(); } /** * 执行任务 */ public void runJob() { // 数据目录 Path dir = Paths.get("test/data/"); try (Stream stream = Files.list(dir)) { // 获取数据目录下的文件列表 List pathList = stream.filter(t -> t.toString().endsWith(".xlsx")).sorted().toList(); log.info("数据文件列表: {}", pathList); if (CollectionUtils.isEmpty(pathList)) { throw new MyRuntimeException("没有文件"); } for (Path path : pathList) { singleJob(path); } } catch (Exception e) { log.error(e.getMessage(), e); } } /** * 处理单个文件 * * @param path 文件路径 */ public void singleJob(Path path) throws Exception { List> list = readFile(path); List> distinctList = dataProcessing(path, list); Path csvPath = toCsv(path, distinctList); } /** * 读取文件 * * @param path 文件路径 */ public List> readFile(Path path) throws Exception { log.info("读取: {}", path); List headers = Stream.of("year_month", "che_pai_hao_he_tong", "che_xing", "che_liang_suo_shu_dan_wei", "he_tong_ming_cheng", "he_tong_bian_hao", "jia_shui_he_ji_jin_e", "bu_han_shui_jin_e", "shui_e", "zu_qi", "che_pai_hao_ti_huan", "ti_huan_nian_yue", "bei_zhu").toList(); try (InputStream inputStream = Files.newInputStream(path); Workbook workbook = new XSSFWorkbook(inputStream) ) { FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator(); List> resultList = new ArrayList<>(); // 读取第一个工作表 Sheet sheet = workbook.getSheetAt(0); // 表头行 Row headerRow = sheet.getRow(0); // 列数 int columnCount = headerRow.getPhysicalNumberOfCells(); log.info("columnCount: {}", columnCount); // 最后行数 int lastRowNum = sheet.getLastRowNum(); log.info("lastRowNum: {}", lastRowNum); if (lastRowNum == 0) { throw new MyRuntimeException(path.getFileName() + " 为空"); } // 遍历行 for (int i = 1; i <= lastRowNum; i++) { Row row = sheet.getRow(i); if (row == null) { continue; } LinkedHashMap rowMap = new LinkedHashMap<>(); // 遍历列 for (int j = 0; j < columnCount; j++) { String value = ""; rowMap.put(headers.get(j), value); Cell cell = row.getCell(j); if (cell == null) { continue; } switch (cell.getCellType()) { case STRING: // 删除字符串空白字符 value = StringUtils.trimAllWhitespace(cell.getStringCellValue()); break; case NUMERIC: if (DateUtil.isCellDateFormatted(cell)) { value = DateUtil.getLocalDateTime(cell.getNumericCellValue()) .format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); break; } value = String.valueOf(cell.getNumericCellValue()); break; case BOOLEAN: value = String.valueOf(cell.getBooleanCellValue()); break; case FORMULA: CellValue cellValue = evaluator.evaluate(cell); switch (cellValue.getCellType()){ case STRING: value = StringUtils.trimAllWhitespace(cellValue.getStringValue()); break; case NUMERIC: value = String.valueOf(cellValue.getNumberValue()); break; default: break; } default: break; } rowMap.put(headers.get(j), value); } resultList.add(rowMap); } return resultList; } } /** * 数据加工 * * @param path 文件路径 * @param list 数据 */ public List> dataProcessing(Path path, List> list) { ObjectMapper objectMapper = new ObjectMapper(); List> resultList = new ArrayList<>(); for (LinkedHashMap map : list) { String yearMonth = map.get("year_month"); Integer yearMonthInteger = Double.valueOf(yearMonth).intValue(); LocalDate localDate = LocalDate.parse( Double.valueOf(yearMonth).intValue() + "01", DateTimeFormatter.ofPattern("yyyyMMdd")); String rawChePaiHaoHeTong = map.get("che_pai_hao_he_tong"); map.put("raw_che_pai_hao_he_tong", rawChePaiHaoHeTong); String chePaiHaoHeTong = carService.getChePai(rawChePaiHaoHeTong); map.put("che_pai_hao_he_tong", chePaiHaoHeTong); String chePaiHeTongFail = carService.chePaiFail(rawChePaiHaoHeTong); map.put("che_pai_he_tong_fail", chePaiHeTongFail); String rawChePaiHaoTiHuan = map.get("che_pai_hao_ti_huan"); map.put("raw_che_pai_hao_ti_huan", rawChePaiHaoTiHuan); String chePaiHaoTiHuan = carService.getChePai(rawChePaiHaoTiHuan); map.put("che_pai_hao_ti_huan", chePaiHaoTiHuan); String chePaiTiHuanFail = carService.chePaiFail(rawChePaiHaoTiHuan); map.put("che_pai_ti_huan_fail", chePaiTiHuanFail); String cheLiangSuoShuDanWei = map.get("che_liang_suo_shu_dan_wei"); String firstUnit = carService.getFirstUnit(cheLiangSuoShuDanWei); map.put("first_unit", firstUnit); String zuQi = map.get("zu_qi"); int zuQiInt = Double.valueOf(zuQi).intValue(); String tiHuanNianYue = map.get("ti_huan_nian_yue"); Integer tiHuanNianYueInteger = StringUtils.hasText(tiHuanNianYue) ? Double.valueOf(tiHuanNianYue).intValue() : null; map.put("che_pai_hao", tiHuanNianYueInteger != null && yearMonthInteger.compareTo(tiHuanNianYueInteger) >= 0 ? chePaiHaoTiHuan : chePaiHaoHeTong); if (StringUtils.hasText(chePaiHaoTiHuan)) { log.info("{} -> {} -> {} -> {}", chePaiHaoHeTong, yearMonthInteger, tiHuanNianYueInteger, tiHuanNianYueInteger != null && yearMonthInteger.compareTo(tiHuanNianYueInteger) >= 0); } map.put("source", path.getFileName().toString()); resultList.add(map); for (int i = 1; i < zuQiInt; i++) { try { LinkedHashMap t = objectMapper.readValue(objectMapper.writeValueAsString(map), TypeFactory.defaultInstance().constructMapType(LinkedHashMap.class, String.class, String.class)); localDate = localDate.plusMonths(1); Integer nextMonthInteger = Integer.valueOf(localDate.format(DateTimeFormatter.ofPattern("yyyyMM"))); t.put("year_month", nextMonthInteger.toString()); t.put("year_no", localDate.format(DateTimeFormatter.ofPattern("yyyy"))); t.put("month_no", localDate.format(DateTimeFormatter.ofPattern("MM"))); t.put("che_pai_hao", tiHuanNianYueInteger != null && nextMonthInteger.compareTo(tiHuanNianYueInteger) >= 0 ? chePaiHaoTiHuan : chePaiHaoHeTong); resultList.add(t); } catch (Exception e) { log.error(e.toString(), e); } } } // 去重 return resultList; } /** * 生成csv * * @param path 源文件路径 * @param list 数据 */ public Path toCsv(Path path, List> list) throws Exception { log.info("去重后条数:{}", list.size()); Files.createDirectories(Paths.get("test/history/")); Path csvPath = Paths.get("test/history/" + path.getFileName() + ".csv"); try (OutputStreamWriter osw = new OutputStreamWriter(Files.newOutputStream(csvPath), StandardCharsets.UTF_8); CSVPrinter printer = new CSVPrinter(osw, CSVFormat.DEFAULT)) { // 添加bom头避免excel乱码 osw.write('\ufeff'); LinkedHashMap header = list.get(0); // 表头 printer.printRecord(header.keySet()); for (LinkedHashMap map : list) { printer.printRecord(map.values()); } } return csvPath; } }