package org.jeecg.modules.weekly.service.impl; import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.enums.WriteDirectionEnum; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.write.merge.AbstractMergeStrategy; import com.alibaba.excel.write.metadata.WriteSheet; import com.alibaba.excel.write.metadata.fill.FillConfig; import com.alibaba.excel.write.metadata.fill.FillWrapper; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import lombok.Data; import org.apache.commons.lang3.Range; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.jeecg.common.util.DateUtils; import org.jeecg.common.util.HolidayUtils; import org.jeecg.modules.weekly.entity.WekEvaluate; import org.jeecg.modules.weekly.feign.SystemClient; import org.jeecg.modules.weekly.feign.model.SysUser; import org.jeecg.modules.weekly.mapper.WekEvaluateMapper; import org.jeecg.modules.weekly.service.IWekEvaluateService; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import java.io.*; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.temporal.TemporalAdjusters; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; /** * @Description: wek_evaluate * @Author: jeecg-boot * @Date: 2024-01-08 * @Version: V1.0 */ @Service public class WekEvaluateServiceImpl extends ServiceImpl implements IWekEvaluateService { @Value(value = "${jeecg.path.upload}") private String uploadpath; @Autowired private SystemClient systemClient; @Override public Map exportEvaluate(String year, String sysOrgCode, String user, Integer quarter) { return exportEvaTemplate(year, sysOrgCode, user, quarter); } private Map exportEvaTemplate(String year, String sysOrgCode, String queryUser, Integer quarter) { Map result = new HashMap<>(); String templateFileName = uploadpath + File.separator + "exportTemplate" + File.separator + "WeeklyEva.xlsx"; //TODO 3D事业部使用特定的模板 if(queryUser == null && sysOrgCode!=null && sysOrgCode.equals("A04A02A01A10")){ templateFileName = uploadpath + File.separator + "exportTemplate" + File.separator + "WeeklyEvaCustom.xlsx"; } String filePath = "export" + File.separator + "绩效汇总-" + DateUtils.date2Str(new Date(), DateUtils.yyyymmddhhmmss.get()) + ".xlsx"; String fileName = uploadpath + File.separator + filePath; Integer yearNum = Integer.parseInt(year); Map res = createStatisticsYearTitle(yearNum,quarter); List> colmuns = new ArrayList<>(); if (res.containsKey("colmuns")) { colmuns = (List>) res.get("colmuns"); } Map config = new HashMap<>(); if (res.containsKey("config")) { config = (Map) res.get("config"); } TreeMap mergeSeason = new TreeMap<>(); if (res.containsKey("mergeSeason")) { mergeSeason = (TreeMap) res.get("mergeSeason"); } TreeMap mergeMonth = new TreeMap<>(); if (res.containsKey("mergeMonth")) { mergeMonth = (TreeMap) res.get("mergeMonth"); } List mergeWeek = new ArrayList<>(); if (res.containsKey("mergeWeek")) { mergeWeek = (List) res.get("mergeWeek"); } File templateFile = new File(templateFileName); try { FileInputStream fileInputStream = new FileInputStream(templateFile); ByteArrayOutputStream bos = new ByteArrayOutputStream(); //原模板只有一个sheet,通过poi复制出需要的sheet个数的模板 XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream); //设置模板的第一个sheet的名称 // workbook.setSheetName(1, basisinfo.get("sheet").toString()); //写到流里 workbook.write(bos); byte[] bArray = bos.toByteArray(); InputStream is = new ByteArrayInputStream(bArray); //输出文件路径 ExcelWriter excelWriter = EasyExcel.write(fileName) .registerWriteHandler(new MyHandler(mergeSeason, mergeMonth, mergeWeek)) .withTemplate(is).build(); WriteSheet writeSheet = EasyExcel.writerSheet().build(); FillConfig horConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build(); horConfig.setForceNewRow(true); excelWriter.fill(new FillWrapper("colmuns", colmuns), horConfig, writeSheet); //构建模版的 序号 部门 项目 职务 Map basInfo = new HashMap<>(); basInfo.put("no", "{data.no}"); basInfo.put("depart", "{data.depart}"); basInfo.put("name", "{data.name}"); basInfo.put("post", "{data.post}"); basInfo.put("year", year); excelWriter.fill(basInfo, writeSheet); // 关闭流 excelWriter.finish(); Map weeklyEvaData = createWeeklyEvaData(colmuns, year, sysOrgCode, queryUser); List> data = (List>) weeklyEvaData.get("hz"); List> subList = (List>) weeklyEvaData.get("gr"); List> monList = (List>) weeklyEvaData.get("mon"); //TODO 3D事业部使用特定的模板 if(queryUser == null && sysOrgCode!=null && sysOrgCode.equals("A04A02A01A10")){ exportEvaDataCustom(data, subList,monList, fileName); }else { exportEvaData(data, subList,monList, fileName); } result.put("size", data == null ? 0 : data.size()); result.put("filePath", filePath); } catch (Exception e) { e.printStackTrace(); } return result; } private String exportEvaData(List> data, List> subList, List> monList ,String templateFileName) { File templateFile = new File(templateFileName); try { FileInputStream fileInputStream = new FileInputStream(templateFile); ByteArrayOutputStream bos = new ByteArrayOutputStream(); //原模板只有一个sheet,通过poi复制出需要的sheet个数的模板 XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream); //设置模板的第一个sheet的名称 // workbook.setSheetName(1, basisinfo.get("sheet").toString()); //写到流里 workbook.write(bos); byte[] bArray = bos.toByteArray(); InputStream is = new ByteArrayInputStream(bArray); //输出文件路径 ExcelWriter excelWriter = EasyExcel.write(templateFileName) .withTemplate(is).build(); WriteSheet writeSheet = EasyExcel.writerSheet().build(); FillConfig fillConfig = new FillConfig(); fillConfig.setForceNewRow(true); excelWriter.fill(new FillWrapper("data", data), fillConfig, writeSheet); // 关闭流 excelWriter.finish(); //exportMon(monList, templateFileName); exportSub(subList,monList, templateFileName); } catch (Exception e) { e.printStackTrace(); return null; } return templateFileName; } private String exportEvaDataCustom(List> data, List> subList, List> monList ,String templateFileName) { File templateFile = new File(templateFileName); try { FileInputStream fileInputStream = new FileInputStream(templateFile); ByteArrayOutputStream bos = new ByteArrayOutputStream(); //原模板只有一个sheet,通过poi复制出需要的sheet个数的模板 XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream); //设置模板的第一个sheet的名称 // workbook.setSheetName(1, basisinfo.get("sheet").toString()); //写到流里 workbook.write(bos); byte[] bArray = bos.toByteArray(); InputStream is = new ByteArrayInputStream(bArray); //输出文件路径 ExcelWriter excelWriter = EasyExcel.write(templateFileName) .withTemplate(is).build(); WriteSheet writeSheet = EasyExcel.writerSheet().build(); FillConfig fillConfig = new FillConfig(); fillConfig.setForceNewRow(true); excelWriter.fill(new FillWrapper("data", data), fillConfig, writeSheet); // 关闭流 excelWriter.finish(); exportMonCustom(monList, templateFileName); exportSubCustom(subList,monList, templateFileName); } catch (Exception e) { e.printStackTrace(); return null; } return templateFileName; } /** * 导出个人部分 * * @param subList * @param templateFileName */ private void exportSub(List> subList,List> monList, String templateFileName) { File templateFile = new File(templateFileName); try { if (subList == null || subList.size() < 1) { return; } FileInputStream fileInputStream = new FileInputStream(templateFile); ByteArrayOutputStream bos = new ByteArrayOutputStream(); //原模板只有一个sheet,通过poi复制出需要的sheet个数的模板 XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream); //设置模板的第一个sheet的名称 Map first = subList.get(0); int index = workbook.getSheetIndex("个人绩效考核汇总表"); /* int remove = workbook.getSheetIndex("绩效分析报告"); if(monList.size()<1){ workbook.removeSheetAt(remove); index-=1; }*/ workbook.setSheetName(index, first.get("name").toString()); for (int i = 0; i < subList.size(); i++) { if (i == 0) continue; Map sub = subList.get(i); workbook.cloneSheet(index, sub.get("name").toString()); } //写到流里 workbook.write(bos); byte[] bArray = bos.toByteArray(); InputStream is = new ByteArrayInputStream(bArray); //输出文件路径 ExcelWriter excelWriter = EasyExcel.write(templateFileName) .withTemplate(is).build(); for (int i = 0; i < subList.size(); i++) { Map sub = subList.get(i); WriteSheet writeSheet = EasyExcel.writerSheet(sub.get("name").toString()) .build(); excelWriter.fill(sub, writeSheet); } // 关闭流 excelWriter.finish(); } catch (Exception e) { e.printStackTrace(); } } private void exportMon(List> monList, String templateFileName) { File templateFile = new File(templateFileName); try { if (monList == null || monList.size() < 1) { return; } FileInputStream fileInputStream = new FileInputStream(templateFile); ByteArrayOutputStream bos = new ByteArrayOutputStream(); //原模板只有一个sheet,通过poi复制出需要的sheet个数的模板 XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream); //设置模板的第一个sheet的名称 Map first = monList.get(0); int sheetIndex = workbook.getSheetIndex("绩效分析报告"); workbook.setSheetName(sheetIndex, first.get("name").toString()); for (int i = 0; i < monList.size(); i++) { if (i == 0) continue; Map sub = monList.get(i); workbook.cloneSheet(sheetIndex, sub.get("name").toString()); } //写到流里 workbook.write(bos); byte[] bArray = bos.toByteArray(); InputStream is = new ByteArrayInputStream(bArray); //输出文件路径 ExcelWriter excelWriter = EasyExcel.write(templateFileName) .withTemplate(is).build(); for (int i = 0; i < monList.size(); i++) { Map mon = monList.get(i); WriteSheet writeSheet = EasyExcel.writerSheet(mon.get("name").toString()) .build(); excelWriter.fill(mon, writeSheet); } // 关闭流 excelWriter.finish(); } catch (Exception e) { e.printStackTrace(); } } /** * 导出个人部分 * * @param subList * @param templateFileName */ private void exportSubCustom(List> subList,List> monList, String templateFileName) { File templateFile = new File(templateFileName); try { if (subList == null || subList.size() < 1) { return; } FileInputStream fileInputStream = new FileInputStream(templateFile); ByteArrayOutputStream bos = new ByteArrayOutputStream(); //原模板只有一个sheet,通过poi复制出需要的sheet个数的模板 XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream); //设置模板的第一个sheet的名称 Map first = subList.get(0); /* int remove = workbook.getSheetIndex("绩效分析报告"); if(monList.size()<1){ workbook.removeSheetAt(remove); index-=1; }*/ int index = workbook.getSheetIndex("个人绩效考核汇总表"); workbook.setSheetName(index, first.get("name").toString()); for (int i = 0; i < subList.size(); i++) { if (i == 0) continue; Map sub = subList.get(i); workbook.cloneSheet(index, sub.get("name").toString()); } //写到流里 workbook.write(bos); byte[] bArray = bos.toByteArray(); InputStream is = new ByteArrayInputStream(bArray); //输出文件路径 ExcelWriter excelWriter = EasyExcel.write(templateFileName) .withTemplate(is).build(); for (int i = 0; i < subList.size(); i++) { Map sub = subList.get(i); WriteSheet writeSheet = EasyExcel.writerSheet(sub.get("name").toString()) .build(); excelWriter.fill(sub, writeSheet); } // 关闭流 excelWriter.finish(); } catch (Exception e) { e.printStackTrace(); } } private void exportMonCustom(List> monList, String templateFileName) { File templateFile = new File(templateFileName); try { if (monList == null || monList.size() < 1) { return; } FileInputStream fileInputStream = new FileInputStream(templateFile); ByteArrayOutputStream bos = new ByteArrayOutputStream(); //原模板只有一个sheet,通过poi复制出需要的sheet个数的模板 XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream); //设置模板的第一个sheet的名称 /* Map first = monList.get(0); int sheetIndex = workbook.getSheetIndex("绩效分析报告"); workbook.setSheetName(sheetIndex, first.get("name").toString()); for (int i = 0; i < monList.size(); i++) { if (i == 0) continue; Map sub = monList.get(i); workbook.cloneSheet(sheetIndex, sub.get("name").toString()); }*/ String names = monList.stream() .map(map -> map.get("name")) // 获取指定字段的值 .filter(Objects::nonNull) // 过滤掉为null的值 .map(Object::toString) // 将字段值转换为字符串 .collect(Collectors.joining(", ")); // 使用逗号拼接所有字符串 for (int i = 1; i <=12 ; i++) { if(!names.contains(i+"月绩效分析报告")){ int sheetIndex = workbook.getSheetIndex(i + "月绩效分析报告"); workbook.removeSheetAt(sheetIndex); } } //写到流里 workbook.write(bos); byte[] bArray = bos.toByteArray(); InputStream is = new ByteArrayInputStream(bArray); //输出文件路径 ExcelWriter excelWriter = EasyExcel.write(templateFileName) .withTemplate(is).build(); for (int i = 0; i < monList.size(); i++) { Map mon = monList.get(i); WriteSheet writeSheet = EasyExcel.writerSheet(mon.get("name").toString()) .build(); excelWriter.fill(mon, writeSheet); } // 关闭流 excelWriter.finish(); } catch (Exception e) { e.printStackTrace(); } } /** * 创建绩效数据 * tips:此处生成key参照weeklyEva模版 * * @param colmuns * @return */ private Map createWeeklyEvaData(List> colmuns, String year, String sysOrgCode, String queryUser) { Map root = new HashMap<>(); List> res = new ArrayList<>(); List> subList = new ArrayList<>(); List> monthAnalysList = new ArrayList<>(); List queryUserList = new ArrayList<>(); if (StringUtils.isNotEmpty(sysOrgCode)) { //过滤选择的部门,选择的用户 List departUserList = systemClient.queryUserByDepCode(sysOrgCode).getResult(); if (departUserList.size() > 0) { queryUserList.addAll(departUserList); } } String userNames = ""; if (queryUserList.size() > 0) { String collect = queryUserList.stream().map(SysUser::getUsername) .collect(Collectors.joining(",")); userNames = collect; } if (StringUtils.isNotEmpty(queryUser)) { if (StringUtils.isNotEmpty(userNames)) { userNames += ","; } userNames += queryUser; } //查询考评记录 QueryWrapper wekEvaluateQueryWrapper = new QueryWrapper<>(); wekEvaluateQueryWrapper.lambda().eq(WekEvaluate::getYear, year); //有查询条件 if (StringUtils.isNotEmpty(userNames)) { wekEvaluateQueryWrapper.lambda().in(WekEvaluate::getZp, Arrays.asList(userNames.split(","))); } List wekEvaluateList = this.list(wekEvaluateQueryWrapper); if (wekEvaluateList.isEmpty()) { return root; } String zpUsersStr = wekEvaluateList.stream().map(WekEvaluate::getZp) .collect(Collectors.joining(",")); List zpUserList = systemClient.queryByNames(zpUsersStr).getResult(); Map userMap = zpUserList.stream() .collect(Collectors.toMap(SysUser::getUsername, sysuser -> sysuser)); //按照个人分组组装数据 Map> wekEvaluategroup = wekEvaluateList.stream().filter(item->StringUtils.isNotEmpty(item.getZp())).collect(Collectors.groupingBy(item -> item.getZp())); //TODO 没有考评数据周的数据默认补充 C patcEvaData(year,wekEvaluategroup, userMap); //月绩效分析报告start TODO //此报表只有视觉研发部才有;必要条件1-视觉研发部(A04A02A01A10) 2-配置部门小组 if(queryUser == null && sysOrgCode!=null && sysOrgCode.equals("A04A02A01A10")){ List> monthList = monthAnalys(wekEvaluategroup, userMap); monthAnalysList.addAll(monthList); } //月绩效分析报告end AtomicInteger index = new AtomicInteger(1); //数据行数 wekEvaluategroup.forEach((user, evaluateList) -> { Map item = new HashMap<>(); Map sub = new HashMap<>(); //汇总表 item.put("no", index.get()); //序号 item.put("name", evaluateList.get(0).getZpName()); //姓名 item.put("depart", userMap.get(user).getOrgCodeTxt()); item.put("post", userMap.get(user).getPost()); //个人表 sub.put("name", evaluateList.get(0).getZpName()); //姓名 sub.put("year", evaluateList.get(0).getYear()); //年 //个人周报数据再按月分组 Map> monEvaMap = evaluateList.stream().collect(Collectors.groupingBy(month -> month.getMonth())); TreeMap> seasonKpScoreMap = new TreeMap<>(); TreeMap> seasonZpScoreMap = new TreeMap<>(); for (int i = 1; i <= 4; i++) { seasonKpScoreMap.put(i, new ArrayList<>()); seasonZpScoreMap.put(i, new ArrayList<>()); } monEvaMap.forEach((mon, monList) -> { //考评分 List monthZpScoreList = new ArrayList<>(); List monthKpScoreList = new ArrayList<>(); //个人周报数据再按周分组 Map> weekEvaMap = monList.stream().collect(Collectors.groupingBy(week -> week.getWeek())); weekEvaMap.forEach((w, wekList) -> { WekEvaluate eva = wekList.get(0); if (eva == null) return; //TODO 重要 此处是year_week 要转成month_week String weekToDayEndStr = DateUtils.weekToDayEndStr(eva.getYear(), eva.getWeek(), "yyyy-MM-dd"); Integer weekInMonth = DateUtils.getWeekInMonth(weekToDayEndStr); if (weekInMonth == null) return; String zpPlan = eva.getZpPlan(); String zpAmount = eva.getZpAmount(); String zpEffe = eva.getZpEffe(); String zpQuality = eva.getZpQuality(); if (StringUtils.isNotEmpty(zpPlan) && StringUtils.isNotEmpty(zpAmount) && StringUtils.isNotEmpty(zpEffe) && StringUtils.isNotEmpty(zpQuality)) { int score = calcEvaScore(zpPlan, zpAmount, zpEffe, zpQuality); //注意 此处生成key要和excel生成head中colnum一致 item.put("w" + eva.getYearWeek() + "_1", score); //个人绩效汇总生成colmun sub.put("m" + mon + "w" + weekInMonth + "_zp1", calScore(zpPlan, 1)); sub.put("m" + mon + "w" + weekInMonth + "_zp2", calScore(zpAmount, 1)); sub.put("m" + mon + "w" + weekInMonth + "_zp3", calScore(zpEffe, 1)); sub.put("m" + mon + "w" + weekInMonth + "_zp4", calScore(zpQuality, 2)); monthZpScoreList.add(score); } String kpPlan = eva.getKpPlan(); String kpAmount = eva.getKpAmount(); String kpEffe = eva.getKpEffe(); String kpQuality = eva.getKpQuality(); if (StringUtils.isNotEmpty(kpPlan) && StringUtils.isNotEmpty(kpAmount) && StringUtils.isNotEmpty(kpEffe) && StringUtils.isNotEmpty(kpQuality)) { int score = calcEvaScore(kpPlan, kpAmount, kpEffe, kpQuality); //注意 此处生成key要和excel生成head中colnum一致 item.put("w" + eva.getYearWeek() + "_2", score); //个人绩效汇总生成colmun sub.put("m" + mon + "w" + weekInMonth + "_kp1", calScore(kpPlan, 1)); sub.put("m" + mon + "w" + weekInMonth + "_kp2", calScore(kpAmount, 1)); sub.put("m" + mon + "w" + weekInMonth + "_kp3", calScore(kpEffe, 1)); sub.put("m" + mon + "w" + weekInMonth + "_kp4", calScore(kpQuality, 2)); monthKpScoreList.add(score); } }); //获取考评附加分 TODO Optional max = monList.stream().filter(score -> score.getKpExtScore() != null).max(Comparator.comparingDouble(WekEvaluate::getKpExtScore)); //考核月平均 考评 double kpScore = monthKpScoreList.stream().mapToDouble(Integer::intValue) .average() .orElse(0); String skpScore = String.format("%.1f", kpScore); double avg = Double.parseDouble(skpScore); if (max.isPresent() && avg > 0) { avg = avg + max.get().getKpExtScore().intValue(); sub.put("m" + mon + "kp_ext_score", max.get().getKpExtScore().intValue()); sub.put("m" + mon + "kp_ext_desc", max.get().getKpExtDesc()); } if (avg == 0) { item.put("m" + mon + "_1", ""); sub.put("m" + mon + "avg_kp", ""); } else { item.put("m" + mon + "_1", avg); sub.put("m" + mon + "avg_kp", avg); } //自评 double zpScore = monthZpScoreList.stream().mapToInt(Integer::intValue) .average() .orElse(0); String szpScore = String.format("%.1f", zpScore); double zpAvg = Double.parseDouble(szpScore); if (zpAvg == 0) { sub.put("m" + mon + "avg_zp", ""); } else { sub.put("m" + mon + "avg_zp", zpAvg); } //个人绩效 //绩效有4项 计划及达成 、工作完成量、工作完成效率、工作完成质量 for (int i = 1; i <= 4; i++) { List subZpList = new ArrayList<>(); List subKpList = new ArrayList<>(); //一个月最多5周 for (int j = 1; j <= 5; j++) { //自评 if (sub.containsKey("m" + mon + "w" + j + "_zp" + i)) { Integer zp = (Integer) sub.get("m" + mon + "w" + j + "_zp" + i); subZpList.add(zp); } //考评 if (sub.containsKey("m" + mon + "w" + j + "_kp" + i)) { Integer kp = (Integer) sub.get("m" + mon + "w" + j + "_kp" + i); subKpList.add(kp); } } //一个月的各项自评分平均值 TODO是否保留小数点 Double zp = subZpList.stream().mapToDouble(Integer::intValue) .average() .orElse(0); Double kp = subKpList.stream().mapToDouble(Integer::intValue) .average() .orElse(0); String szp = String.format("%.1f", zp); String skp = String.format("%.1f", kp); zp = Double.parseDouble(szp); kp = Double.parseDouble(skp); if (zp > 0) { sub.put("m" + mon + "avg" + "_zp" + i, zp); } else { sub.put("m" + mon + "avg" + "_zp" + i, ""); } if (kp > 0) { sub.put("m" + mon + "avg" + "_kp" + i, kp); } else { sub.put("m" + mon + "avg" + "_kp" + i, ""); } } //月绩效等级 String monLevel = "C"; String monPay = "100%"; if (avg == 0) { monLevel = ""; monPay = ""; } else if (avg >= 95) { monPay = "140%"; monLevel = "A"; } else if (avg <= 95 && avg >= 85) { monLevel = "B"; monPay = "110%"; } else if (avg <= 84 && avg >= 75) { monLevel = "C"; monPay = "100%"; } else if (avg <= 74 && avg >= 60) { monLevel = "D"; monPay = "90%"; } else if (avg <= 59) { monLevel = "E"; monPay = "不合格"; } item.put("m" + mon + "_2", monLevel); item.put("m" + mon + "_3", monPay); //根据季添加考评分 if (mon <= 3) { seasonZpScoreMap.get(1).add(zpAvg); seasonKpScoreMap.get(1).add(avg); Optional firstEva = monList.stream().filter(i -> i.getKpName() != null).max((i1, i2) -> i1.getKpDate().compareTo(i2.getKpDate())); if (firstEva.isPresent() && StringUtils.isNotEmpty(firstEva.get().getKpName())) { sub.put("s1_kpName", firstEva.get().getKpName()); } if (firstEva.isPresent() && firstEva.get().getKpDate() != null) { sub.put("s1_kpDate", DateUtils.date2Str(firstEva.get().getKpDate(), DateUtils.date_sdf.get())); } } else if (mon >= 4 && mon <= 6) { seasonZpScoreMap.get(2).add(zpAvg); seasonKpScoreMap.get(2).add(avg); Optional firstEva = monList.stream().filter(i -> i.getKpName() != null).max((i1, i2) -> i1.getKpDate().compareTo(i2.getKpDate())); if (firstEva.isPresent() && StringUtils.isNotEmpty(firstEva.get().getKpName())) { sub.put("s2_kpName", firstEva.get().getKpName()); } if (firstEva.isPresent() && firstEva.get().getKpDate() != null) { sub.put("s2_kpDate", DateUtils.date2Str(firstEva.get().getKpDate(), DateUtils.date_sdf.get())); } } else if (mon >= 7 && mon <= 9) { seasonZpScoreMap.get(3).add(zpAvg); seasonKpScoreMap.get(3).add(avg); Optional firstEva = monList.stream().filter(i -> i.getKpName() != null).max((i1, i2) -> i1.getKpDate().compareTo(i2.getKpDate())); if (firstEva.isPresent() && StringUtils.isNotEmpty(firstEva.get().getKpName())) { sub.put("s3_kpName", firstEva.get().getKpName()); } if (firstEva.isPresent() && firstEva.get().getKpDate() != null) { sub.put("s3_kpDate", DateUtils.date2Str(firstEva.get().getKpDate(), DateUtils.date_sdf.get())); } } else if (mon >= 10 && mon <= 12) { seasonZpScoreMap.get(4).add(zpAvg); seasonKpScoreMap.get(4).add(avg); Optional firstEva = monList.stream().filter(i -> i.getKpName() != null).max((i1, i2) -> i1.getKpDate().compareTo(i2.getKpDate())); if (firstEva.isPresent() && StringUtils.isNotEmpty(firstEva.get().getKpName())) { sub.put("s4_kpName", firstEva.get().getKpName()); } if (firstEva.isPresent() && firstEva.get().getKpDate() != null) { sub.put("s4_kpDate", DateUtils.date2Str(firstEva.get().getKpDate(), DateUtils.date_sdf.get())); } } }); seasonKpScoreMap.forEach((season, seasonScoreList) -> { //季平均 double score = seasonScoreList.stream().mapToDouble(Double::doubleValue) .average() .orElse(0); String savg = String.format("%.1f",score); double avg = Double.parseDouble(savg); if (score == 0) { item.put("s" + season + "_1", ""); sub.put("s" + season + "avg_kp", ""); } else { item.put("s" + season + "_1", avg); sub.put("s" + season + "avg_kp", avg); } //季绩效等级 String seasonLevel = "C"; String seasonPay = "100%"; if (score == 0) { seasonLevel = ""; seasonPay = ""; } else if (score >= 95) { seasonLevel = "A"; seasonPay = "140%"; } else if (score <= 95 && score >= 85) { seasonLevel = "B"; seasonPay = "110%"; } else if (score <= 84 && score >= 75) { seasonLevel = "C"; seasonPay = "100%"; } else if (score <= 74 && score >= 60) { seasonLevel = "D"; seasonPay = "90%"; } else if (score <= 59) { seasonLevel = "E"; seasonPay = "不合格"; } item.put("s" + season + "_2", seasonLevel); item.put("s" + season + "_3", seasonPay); sub.put("s" + season + "level", seasonLevel); sub.put("s" + season + "pay", seasonPay); }); seasonZpScoreMap.forEach((season, seasonScoreList) -> { //季平均 double score = seasonScoreList.stream().mapToDouble(Double::doubleValue) .average() .orElse(0); String savg = String.format("%.1f", score); double avg = Double.parseDouble(savg); if (avg == 0) { sub.put("s" + season + "avg_zp", ""); } else { sub.put("s" + season + "avg_zp", avg); } }); res.add(item); subList.add(sub); index.getAndIncrement(); }); //对不存在的数据添加空数据,避免导出excel不渲染 for (int i = 0; i < res.size(); i++) { Map d = res.get(i); for (int j = 0; j < colmuns.size(); j++) { Map c = colmuns.get(j); String column = c.get("column").toString().replace("{data.", "").replace("}", ""); String colStr = ""; for (String key : d.keySet()) { colStr += key; colStr += ","; } if (!colStr.contains(column)) { res.get(i).put(column, ""); } } } //汇总数据 root.put("hz", res); //个人数据 root.put("gr", subList); //月度绩效分析报告 root.put("mon", monthAnalysList); return root; } /** * 补齐没有考评的绩效数据,默认C绩效 * * @param wekEvaluategroup */ private void patcEvaData(String yearstr,Map> wekEvaluategroup, Map userMap) { //1.获取今天是今年的多少周 int curWeekInYear = DateUtils.getCurWeek(); int curYear = DateUtils.getCurYear(); int year = Integer.parseInt(yearstr); if(year!=curYear) curWeekInYear = 52; int finalCurWeekInYear = curWeekInYear; wekEvaluategroup.forEach((user, evaList) -> { Map userEvaMap = evaList.stream() .collect(Collectors.toMap(WekEvaluate::getWeek, evaluate -> evaluate)); Map holidayWeek = HolidayUtils.getHolidayWeek(year); for (int i = 1; i <= finalCurWeekInYear; i++) { //TODO 判断是否法定节假日 一周都是法定节假日的情况下,不计算绩效 if(holidayWeek.containsKey(i)) continue; if (!userEvaMap.containsKey(i)) { WekEvaluate e = new WekEvaluate(); e.setZpPlan("C"); e.setZpAmount("C"); e.setZpEffe("C"); e.setZpQuality("C"); e.setKpPlan("C"); e.setKpAmount("C"); e.setKpEffe("C"); e.setKpQuality("C"); e.setYear(year); e.setMonth(DateUtils.yearweekInMonth(year,i)); e.setWeek(i); e.setZp(user); e.setZpName(userMap.get(user).getRealname()); e.setYearWeek(year * 100 + i); evaList.add(e); //检测评分是否遗漏,遗漏默认填充C } else { WekEvaluate wek = userEvaMap.get(i); if (StringUtils.isEmpty(wek.getZpPlan())) wek.setZpPlan("C"); if (StringUtils.isEmpty(wek.getZpAmount())) wek.setZpAmount("C"); if (StringUtils.isEmpty(wek.getZpEffe())) wek.setZpEffe("C"); if (StringUtils.isEmpty(wek.getZpQuality())) wek.setZpQuality("C"); if (StringUtils.isEmpty(wek.getKpPlan())) wek.setKpPlan("C"); if (StringUtils.isEmpty(wek.getKpAmount())) wek.setKpAmount("C"); if (StringUtils.isEmpty(wek.getKpEffe())) wek.setKpEffe("C"); if (StringUtils.isEmpty(wek.getKpQuality())) wek.setKpQuality("C"); //替换元素 evaList.replaceAll(item -> item.getId() != null && item.getId().equals(wek.getId()) ? wek : item); } } wekEvaluategroup.put(user, evaList); }); } /** * 组装月绩效分析报告 sheet2 */ private List> monthAnalys(Map> wekEvaluategroup,Map userMap) { List> res = new ArrayList<>(); List levList = Arrays.asList("A", "B", "C", "D", "E"); List allData = new ArrayList<>(); Map> wekGroup = deepCopyMap(wekEvaluategroup); //查询用户的小组信息 wekGroup.forEach((user, evaluateList) -> { evaluateList.forEach(item->{ if(userMap.containsKey(item.getZp())){ item.setTeamName(userMap.get(item.getZp()).getTeamName()); } }); evaluateList = evaluateList.stream().filter(i->i.getTeamName()!=null).collect(Collectors.toList()); allData.addAll(evaluateList); }); //个人周报数据按月分组 Map> monEvaMap = allData.stream().collect(Collectors.groupingBy(month -> month.getMonth())); monEvaMap.forEach((mon, monList) -> { Map uMap = new HashMap<>(); uMap.put("name", mon + "月绩效分析报告"); Map cMap = new HashMap<>(); //1.先把abcd转成对应分数 TODO 查询部门小组并进行分组 monList = monList.stream().map(item -> { int kpPlan = calScore(item.getKpPlan(), 1); item.setKpPlan(kpPlan + ""); int kpAmount = calScore(item.getKpAmount(), 1); item.setKpAmount(kpAmount + ""); int kpEffe = calScore(item.getKpEffe(), 1); item.setKpEffe(kpEffe + ""); int kpQuality = calScore(item.getKpQuality(), 2); item.setKpQuality(kpQuality + ""); return item; }).collect(Collectors.toList()); //数据按人分组 Map> userEvaMap = monList.stream().collect(Collectors.groupingBy(month -> month.getZp())); userEvaMap.forEach((user, evaList) -> { uMap.put(user + "_0", evaList.get(0).getZpName()); List> kpMapList = evaList.stream().map(i -> { Map item = new HashMap<>(); item.put("kpPlan", i.getKpPlan()); item.put("kpAmount", i.getKpAmount()); item.put("kpEffe", i.getKpEffe()); item.put("kpQuality", i.getKpQuality()); item.put("team", i.getTeamName()); return item; }).collect(Collectors.toList()); //计算一个月各项考评分平均值 double kpPlan = kpMapList.stream().mapToDouble(map -> Double.parseDouble(map.get("kpPlan").toString())).average().orElse(0.0); double kpAmount = kpMapList.stream().mapToDouble(map ->Double.parseDouble( map.get("kpAmount").toString())).average().orElse(0.0); double kpEffe = kpMapList.stream().mapToDouble(map -> Double.parseDouble(map.get("kpEffe").toString())).average().orElse(0.0); double kpQuality = kpMapList.stream().mapToDouble(map -> Double.parseDouble(map.get("kpQuality").toString())).average().orElse(0.0); String skpPlan = String.format("%.1f", kpPlan); kpPlan = Double.parseDouble(skpPlan); String skpAmount = String.format("%.1f", kpAmount); kpAmount = Double.parseDouble(skpAmount); String skpEffe = String.format("%.1f", kpEffe); kpEffe = Double.parseDouble(skpEffe); String skpQuality = String.format("%.1f", kpQuality); kpQuality = Double.parseDouble(skpQuality); uMap.put(user + "_1", kpPlan); uMap.put(user + "_2", kpAmount); uMap.put(user + "_3", kpEffe); uMap.put(user + "_4", kpQuality); double total = kpPlan + kpAmount + kpEffe + kpQuality; String stotal = String.format("%.1f", total); total = Double.parseDouble(stotal); uMap.put(user + "_5", total); String level = scoreCalcLevel(total); uMap.put(user + "_6", level); for (int i = 0; i >> teamGroupMap = kpMapList.stream() .collect(Collectors.groupingBy(map -> map.get("team").toString())); AtomicReference team = new AtomicReference<>("team1"); teamGroupMap.forEach((group,list)->{ double tkpPlan = list.stream().mapToDouble(map ->Double.parseDouble( map.get("kpPlan").toString())).average().orElse(0.0); double tkpAmount = list.stream().mapToDouble(map ->Double.parseDouble( map.get("kpAmount").toString())).average().orElse(0.0); double tkpEffe = list.stream().mapToDouble(map ->Double.parseDouble( map.get("kpEffe").toString())).average().orElse(0.0); double tkpQuality = list.stream().mapToDouble(map ->Double.parseDouble( map.get("kpQuality").toString())).average().orElse(0.0); if(group.equals("ARM软件")){ team.set("team1"); }else if(group.equals("上位机")){ team.set("team2"); }else if(group.equals("硬件")){ team.set("team3"); }else if(group.equals("产品")){ team.set("team4"); }else if(group.equals("营销")){ team.set("team5"); } String stkpPlan = String.format("%.1f", tkpPlan); tkpPlan = Double.parseDouble(stkpPlan); String stkpAmount = String.format("%.1f", tkpAmount); tkpAmount = Double.parseDouble(stkpAmount); String stkpEffe = String.format("%.1f", tkpEffe); tkpEffe = Double.parseDouble(stkpEffe); String stkpQuality = String.format("%.1f", tkpQuality); tkpQuality = Double.parseDouble(stkpQuality); uMap.put( team.get() +"_1", tkpPlan); uMap.put( team.get() +"_2", tkpAmount); uMap.put( team.get() +"_3", tkpEffe); uMap.put( team.get() +"_4", tkpQuality); double ttotal = tkpPlan + tkpAmount + tkpEffe + tkpQuality; String sttotal = String.format("%.1f", ttotal); ttotal = Double.parseDouble(sttotal); uMap.put( team.get() +"_5", ttotal); }); }); StringBuilder info = new StringBuilder(); cMap.forEach((k,v)->{ info.append( k +"共" + v +"人,"); }); levList.forEach(level->{ if (cMap.containsKey(level)){ uMap.put("count"+level,cMap.get(level)); }else { uMap.put("count"+level,0); } }); // 查找最后一个逗号的位置 int lastCommaIndex = info.lastIndexOf(","); if (lastCommaIndex >= 0) { // 构建新的字符串,将最后一个逗号替换为空字符串 String output = info.substring(0, lastCommaIndex) + info.substring(lastCommaIndex + 1); uMap.put("info",output); } res.add(uMap); }); return res; } private String scoreCalcLevel(Double score) { if (score >= 95) { return "A"; } else if (score >= 85) { return "B"; } else if (score >= 75) { return "C"; } else if (score >= 60) { return "D"; } return "E"; } // 进行深拷贝 public Map> deepCopyMap(Map> originalMap) { Map> copiedMap = new HashMap<>(); for (Map.Entry> entry : originalMap.entrySet()) { String key = entry.getKey(); List originalList = entry.getValue(); List copiedList = new ArrayList<>(originalList.size()); // 深拷贝列表中的每个元素 for (WekEvaluate wekEvaluate : originalList) { WekEvaluate copiedWekEvaluate = new WekEvaluate(); // 假设 WekEvaluat BeanUtils.copyProperties(wekEvaluate, copiedWekEvaluate);// e 类有复制构造函数 copiedList.add(copiedWekEvaluate); } copiedMap.put(key, copiedList); } return copiedMap; } /** * 计算一周考评分 * * @param a * @param b * @param c * @param d * @return */ private int calcEvaScore(String a, String b, String c, String d) { int i = calScore(a, 1); int i1 = calScore(b, 1); int i2 = calScore(c, 1); int i3 = calScore(d, 2); return i + i1 + i2 + i3; } /** * 计算每项考评分 * * @param kp * @param type * @return */ private int calScore(String kp, int type) { int score = 0; switch (kp) { case "A": score = 19 * type; break; case "B": score = 17 * type; break; case "C": score = 15 * type; break; case "D": score = 12 * type; break; case "E": score = 5 * type; break; } return score; } /** * @param quarter 季度 0-全年 1-2-3-4 * @return */ public Map createStatisticsYearTitle(Integer year, Integer quarter) { Map root = new HashMap<>(); //title List> res = new ArrayList<>(); //周号对应colmun Map map = new HashMap<>(); //需要合并的行或列信息 TreeMap mergeSeason = new TreeMap<>(); TreeMap mergeMonth = new TreeMap<>(); //当前年 int curYear = year; //根据 当前季度 得到月份区间 Range monRange = Range.between(quarter * 3 - 2, quarter * 3 == 0 ? 12 : quarter * 3); //统计一年有多少周 int yearWeekCount = 0; //int sort = 0; //季 int seasonCount = 1; LocalDate firstSundayOfYear = getFirstSundayOfYear(year); //一年12个月 for (int i = 1; i <= 12; i++) { LocalDate date = LocalDate.of(curYear, i, 1); //获取当月第一天是星期几 int week = date.getDayOfWeek().getValue(); //这个月最后一天 date = date.with(TemporalAdjusters.lastDayOfMonth()); //获取这天是这个月的第几天 int dayOfMonth = date.getDayOfMonth(); //统计一个月有多少周 (TODO :此处分周逻辑保持和周报获取周逻辑一致,定义周日在哪个月则设定本周属于哪个月) // int monthWeekCount = 0; for (int j = 1; j <= dayOfMonth; j++) { LocalDate everyDay = LocalDate.of(curYear, i, j); int d = everyDay.getDayOfWeek().getValue(); //System.err.println("日期:" + everyDay + "-星期:" + d); if (d % 7 == 0) { //判断当年第一天是否周一,不是则第一周不计数 LocalDate first = LocalDate.of(year,1,1); int fd = first.getDayOfWeek().getValue(); //TODO 特殊处理,一年第一个月的第一周必须是一个完整的周一到周日 if(fd!=1 && firstSundayOfYear.isEqual(everyDay)){ continue; } // monthWeekCount++; yearWeekCount++; //System.err.println("周:"+yearWeekCount); //System.err.println("日期:"+everyDay.toString()); //sort++; String weekToDayStartStr = DateUtils.weekToDayStartStr(year,yearWeekCount); String weekToDayEndStr = DateUtils.weekToDayEndStr(year,yearWeekCount); String endstr = DateUtils.weekToDayEndStr(year,yearWeekCount,"yyyy-MM-dd"); Integer weekInMonth = DateUtils.getWeekInMonth(endstr); Integer curMonth = DateUtils.yearweekInMonth(year, yearWeekCount); //System.out.println(i + "月:" + monthWeekCount + "周-No:" + yearWeekCount + "------" + weekToDayStartStr + "==" + weekToDayEndStr); //添加每个月的周 Map weekMap = new HashMap<>(); weekMap.put("title", curMonth + "月第" + weekInMonth + "周"); weekMap.put("month", curMonth + "月"); weekMap.put("week", "第" + weekInMonth + "周"); weekMap.put("season", seasonCount + "季度"); weekMap.put("column", "{data.w" + (curYear * 100 + yearWeekCount) + "_1}"); weekMap.put("wstart", weekToDayStartStr); weekMap.put("wend", weekToDayEndStr); weekMap.put("wno", yearWeekCount); weekMap.put("type", "自评"); weekMap.put("sort", seasonCount*10000 + curMonth *100 + weekInMonth *10 +1); //weekMap.put("curWeek", DateUtils.getCurWeek()); //只添加当前季度数据 if (monRange.contains(i)) { res.add(weekMap); } //System.err.println(weekMap); //sort++; Map weekMap2 = new HashMap<>(); weekMap2.put("title", curMonth + "月第" + weekInMonth + "周"); weekMap2.put("month", curMonth + "月"); weekMap2.put("week", "第" + weekInMonth + "周"); weekMap2.put("season", seasonCount + "季度"); weekMap2.put("column", "{data.w" + (curYear * 100 + yearWeekCount) + "_2}"); weekMap2.put("wstart", weekToDayStartStr); weekMap2.put("wend", weekToDayEndStr); weekMap2.put("wno", yearWeekCount); weekMap2.put("type", "考评"); weekMap2.put("sort", seasonCount*10000 + curMonth *100 + weekInMonth *10 +2); //只添加当前季度数据 if (monRange.contains(i)) { res.add(weekMap2); } map.put(yearWeekCount, "m" + i + "w" + weekInMonth); } } //sort++; //每个月加考评平均分 //月度 Map mon1 = new HashMap<>(); mon1.put("season", seasonCount + "季度"); mon1.put("week", "月度"); mon1.put("month", i + "月绩效"); mon1.put("column", "{data.m" + i + "_1}"); mon1.put("type", "月度"); mon1.put("sort", seasonCount*10000 + i *100 + 90); //只添加当前季度数据 if (monRange.contains(i)) { res.add(mon1); } //sort++; //绩效等级 Map mon2 = new HashMap<>(); mon2.put("season", seasonCount + "季度"); mon2.put("week", "绩效等级"); mon2.put("month", i + "月绩效"); mon2.put("column", "{data.m" + i + "_2}"); mon2.put("type", "绩效等级"); mon2.put("sort", seasonCount*10000 + i *100 + 91); //只添加当前季度数据 if (monRange.contains(i)) { res.add(mon2); } //sort++; //发放比例 Map mon3 = new HashMap<>(); mon3.put("season", seasonCount + "季度"); mon3.put("week", "发放比例"); mon3.put("month", i + "月绩效"); mon3.put("column", "{data.m" + i + "_3}"); mon3.put("type", "发放比例"); mon3.put("sort", seasonCount*10000 + i *100 + 92); //只添加当前季度数据 if (monRange.contains(i)) { res.add(mon3); } //季 if (i % 3 == 0) { //sort++; //发放比例 Map s1 = new HashMap<>(); s1.put("season", seasonCount + "季度"); s1.put("week", "季度"); s1.put("month", seasonCount + "季度绩效"); s1.put("column", "{data.s" + seasonCount + "_1}"); s1.put("type", "季度"); s1.put("sort", seasonCount*10000 + 9000); //只添加当前季度数据 if (quarter == 0 || seasonCount == quarter) { res.add(s1); } //sort++; //发放比例 Map s2 = new HashMap<>(); s2.put("season", seasonCount + "季度"); s2.put("week", "绩效等级"); s2.put("month", seasonCount + "季度绩效"); s2.put("column", "{data.s" + seasonCount + "_2}"); s2.put("type", "绩效等级"); s2.put("sort", seasonCount*10000 + 9100); //只添加当前季度数据 if (quarter == 0 || seasonCount == quarter) { res.add(s2); } //sort++; //发放比例 Map s3 = new HashMap<>(); s3.put("season", seasonCount + "季度"); s3.put("week", "发放比例"); s3.put("month", seasonCount + "季度绩效"); s3.put("column", "{data.s" + seasonCount + "_3}"); s3.put("type", "发放比例"); s3.put("sort", seasonCount*10000 + 9200); //只添加当前季度数据 if (quarter == 0 || seasonCount == quarter) { res.add(s3); } seasonCount++; } } root.put("colmuns", res); root.put("config", map); //System.err.println("-------------------------------------"); //System.err.println(JSON.toJSON(res)); //计算合并数据 //1.季度 Map>> seasonMap = res.stream().collect(Collectors.groupingBy(item -> item.get("season"))); seasonMap.forEach((season, list) -> { //季度 Integer s = Integer.parseInt(season.toString().replaceAll("\\D+", "")); int size = list.size(); mergeSeason.put(s, size); }); //2.月 List monMergeList = new ArrayList<>(); List wekMergeList = new ArrayList<>(); AtomicReference monMergeIndex = new AtomicReference<>(1); res.forEach(item -> { String month = (String) item.get("month"); MergeBean bean = new MergeBean(); bean.setCol(month); bean.setSort(monMergeIndex.get()); monMergeIndex.getAndSet(monMergeIndex.get() + 1); monMergeList.add(bean); String week = (String) item.get("week"); MergeBean bean2 = new MergeBean(); bean2.setCol(week); bean2.setSort(monMergeIndex.get()); monMergeIndex.getAndSet(monMergeIndex.get() + 1); wekMergeList.add(bean2); }); Map> monGroupList = monMergeList.stream().collect(Collectors.groupingBy( item -> item.getCol(), LinkedHashMap::new, Collectors.toList())); List mergeWeek = new ArrayList<>(); LinkedHashMap>> collect = res.stream().collect(Collectors.groupingBy(item -> item.get("month").toString(), LinkedHashMap::new, Collectors.toList())); collect.forEach((m, list) -> { LinkedHashMap>> week = list.stream().collect(Collectors.groupingBy(item -> item.get("week").toString(), LinkedHashMap::new, Collectors.toList())); week.forEach((w, weekList) -> { mergeWeek.add(weekList.size()); }); }); monGroupList.forEach((key, list) -> { mergeMonth.put(mergeMonth.size(), list.size()); }); root.put("mergeSeason", mergeSeason); root.put("mergeMonth", mergeMonth); root.put("mergeWeek", mergeWeek); return root; } public LocalDate getFirstSundayOfYear(int year) { LocalDate date = LocalDate.of(year, 1, 1); // 找到给定年份中第一个周日的日期 while (date.getDayOfWeek() != DayOfWeek.SUNDAY) { date = date.plusDays(1); } return date; } @Data public class MergeBean { private String col; private String alias; private Integer count; private Integer sort; } class MyHandler extends AbstractMergeStrategy { private Map mergeSeason; private Map mergeMonth; private List mergeWeek; public MyHandler(Map mergeSeason, Map mergeMonth, List mergeWeek) { this.mergeSeason = mergeSeason; this.mergeMonth = mergeMonth; this.mergeWeek = mergeWeek; } @Override protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) { //合并单元格,根据模板手动计算合并单元格坐标 Integer seasonStartRow = 1; AtomicReference seasonStartCol = new AtomicReference<>(4); AtomicReference seasonEndCol = new AtomicReference<>(0); mergeSeason.forEach((type, value) -> { //1.合并四季的title seasonEndCol.set(seasonStartCol.get() + (value - 1)); if (cell.getRowIndex() == seasonStartRow && cell.getColumnIndex() == seasonStartCol.get()) { CellRangeAddress cellAddresses = new CellRangeAddress(seasonStartRow, seasonStartRow, seasonStartCol.get(), seasonEndCol.get()); sheet.addMergedRegionUnsafe(cellAddresses); } seasonStartCol.set(seasonStartCol.get() + (value - 1) + 1); }); Integer monthStartRow = 2; AtomicReference monthStartCol = new AtomicReference<>(4); AtomicReference monthEndCol = new AtomicReference<>(0); mergeMonth.forEach((type, value) -> { //1.合并月的title monthEndCol.set(monthStartCol.get() + (value - 1)); if (cell.getRowIndex() == monthStartRow && cell.getColumnIndex() == monthStartCol.get()) { CellRangeAddress cellAddresses = new CellRangeAddress(monthStartRow, monthStartRow, monthStartCol.get(), monthEndCol.get()); sheet.addMergedRegionUnsafe(cellAddresses); } monthStartCol.set(monthStartCol.get() + (value - 1) + 1); }); Integer weekStartRow = 3; AtomicReference weekStartCol = new AtomicReference<>(4); AtomicReference weekEndCol = new AtomicReference<>(0); mergeWeek.forEach((value) -> { //1.合并周的title weekEndCol.set(weekStartCol.get() + (value - 1)); if (cell.getRowIndex() == weekStartRow && cell.getColumnIndex() == weekStartCol.get()) { if (value == 1) { CellRangeAddress cellAddresses = new CellRangeAddress(weekStartRow, weekStartRow + 1, weekStartCol.get(), weekEndCol.get()); sheet.addMergedRegionUnsafe(cellAddresses); } else { CellRangeAddress cellAddresses = new CellRangeAddress(weekStartRow, weekStartRow, weekStartCol.get(), weekEndCol.get()); sheet.addMergedRegionUnsafe(cellAddresses); } } weekStartCol.set(weekStartCol.get() + (value - 1) + 1); }); if (relativeRowIndex == null || relativeRowIndex == 0) { return; } } } }