diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index 72d888f..b266507 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -118,6 +118,16 @@ javax.servlet javax.servlet-api + diff --git a/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/controller/KhGatherController.java b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/controller/KhGatherController.java index 20060cb..526f60d 100644 --- a/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/controller/KhGatherController.java +++ b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/controller/KhGatherController.java @@ -1,6 +1,8 @@ package com.ruoyi.kaohe.controller; +import java.io.IOException; import java.math.BigDecimal; +import java.net.URLEncoder; import java.util.*; import javax.servlet.http.HttpServletResponse; @@ -9,6 +11,7 @@ import com.ruoyi.kaohe.domain.KhKhrwResult; import com.ruoyi.kaohe.service.IKhKhrwResultService; import com.ruoyi.kaohe.service.IKhVoteEmpService; import com.ruoyi.kaohe.service.IKhVoteService; +import com.ruoyi.kaohe.util.EnhancedJsonExporter; import com.ruoyi.kaohe.util.JsonDeepMerge; import com.ruoyi.kaohe.util.PinYinUtil; import org.json.JSONArray; @@ -97,6 +100,16 @@ public class KhGatherController extends BaseController { tabledata.putAll(hz_df); //根据被考核对象名分组数据到map中 得到表格内容的最终数据 JSONArray endTableData = JsonDeepMerge.mergeByKey(tabledata, "khdx"); + //把数据结果中的khdx这个键值对———放到汇总主题拼音的key值里面 + for (Object endData : endTableData) { + JSONObject jsonData = (JSONObject) endData; + String khdx = jsonData.getString("khdx"); + JSONObject hzData = jsonData.getJSONObject(pyhz_name); + hzData.put("khdx",khdx); + jsonData.remove("khdx"); + jsonData.put(pyhz_name,hzData); + endData=jsonData; + } KhGather gather = new KhGather(); gather.setHzName(hz_name); @@ -117,7 +130,6 @@ public class KhGatherController extends BaseController { private Map parseJson(JSONArray datas, String titleP, BigDecimal z_zb) throws JsonProcessingException { Map result = new HashMap<>(); - JSONArray hz_df = new JSONArray();//存储标题占比时的得分 JSONArray title_df = new JSONArray();//处理标题占比时的得分 String pyTitle = PinYinUtil.getPinyinInitials(titleP);//父级表头 JSONObject btKhdx = new JSONObject(true); //表头考核对象存储 @@ -311,13 +323,24 @@ public class KhGatherController extends BaseController { /** * 导出生成汇总列表 */ - @PreAuthorize("@ss.hasPermi('kaohe:gather:export')") + /*@PreAuthorize("@ss.hasPermi('kaohe:gather:export')") @Log(title = "生成汇总", businessType = BusinessType.EXPORT) @PostMapping("/export") public void export(HttpServletResponse response, KhGather khGather) { List list = khGatherService.selectKhGatherList(khGather); ExcelUtil util = new ExcelUtil(KhGather.class); util.exportExcel(response, list, "生成汇总数据"); + }*/ + @PreAuthorize("@ss.hasPermi('kaohe:gather:export')") + @Log(title = "生成汇总", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, Long id) throws Exception { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("汇总数据.xlsx", "UTF-8")); + KhGather gather = khGatherService.selectKhGatherById(id); + String tableHeader = gather.getTableHeader(); + String tableData = gather.getTableData(); + EnhancedJsonExporter.exportWithMergedHeader(tableHeader,tableData,response); } /** diff --git a/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/controller/KhKhrwResultController.java b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/controller/KhKhrwResultController.java index 623c28c..aed4af2 100644 --- a/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/controller/KhKhrwResultController.java +++ b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/controller/KhKhrwResultController.java @@ -58,155 +58,7 @@ public class KhKhrwResultController extends BaseController { if(khKhrwResults!=null&&khKhrwResults.size()>0){ return AjaxResult.error("该考核任务已有生成结果!"); } - - /* JSONArray header = new JSONArray();//存放表头及表格关联数据 - JSONObject headerData = new JSONObject(); - headerData.put("name", null); - headerData.put("label", pc.getPcTitle());*/ - JSONArray children = new JSONArray(); - JSONObject tableColumn = new JSONObject(); - tableColumn.put("name", "khdx"); - if (pc.getBkhdxType().equals("0")) { - tableColumn.put("label", "单位"); - } else { - tableColumn.put("label", "姓名"); - } - children.add(tableColumn); - - JSONObject tableColumn2 = new JSONObject(); - String pyPCtitle = PinYinUtil.getPinyinInitials(pc.getPcTitle()); - tableColumn2.put("name", pyPCtitle); - tableColumn2.put("label", pc.getPcTitle()); - -//----------------------------------------------------------------------------------------- - - JSONArray endData = new JSONArray(); //存放表格数据 - List lists = new ArrayList<>(); - - KhVote khVote = new KhVote(); - khVote.setPingceId(pc.getId()); - //查询该考核任务下的所有评分任务 - List votes = khVoteService.selectKhVoteList(khVote); - for (KhVote vote : votes) { - KhVoteEmp khVoteEmp = new KhVoteEmp(); - khVoteEmp.setVoteId(vote.getId()); - //查询该评分任务对应的所有被考核对象详情 - List khVoteEmps = voteEmpService.selectKhVoteEmpList(khVoteEmp); - lists.addAll(khVoteEmps); - } - //根据被考核对象名分组数据到map中 - Map> khdxMap = lists.stream() - .collect(Collectors.groupingBy(KhVoteEmp::getBkhdxName, - LinkedHashMap::new, // 使用LinkedHashMap保持插入顺序(这对于键很重要) - Collectors.toList())); // 根据getBkhdxName分组*/lists.stream(). - //循环map得到对应数据 - Set>> entries = khdxMap.entrySet(); - Integer index1=0; - for (Map.Entry> entry : entries) { - index1++; - BigDecimal sumScore = BigDecimal.ZERO; - String key = entry.getKey(); - //获取表头数据 - List children2 = new ArrayList<>(); -//------------------------------------------------------------------------------------------------------ - - //获取表数据 - JSONObject pcdata = new JSONObject(); - List value = entry.getValue(); - JSONObject votesDatas = new JSONObject(); - Integer index2 = 0; - for (KhVoteEmp voteEmp : value) { - index2++; - JSONObject tabledata = new JSONObject(); - tabledata.put("name", "khx"+index2); - tabledata.put("label", voteEmp.getVoteTitle()); - - Object objectData; - //根据考核类型存储不同数据 - if (voteEmp.getKhitemTypeid().equals(1L)) { //评分选项 - KhXxpf xxpf = new KhXxpf(); - xxpf.setOptionA(voteEmp.getOptionA()); - xxpf.setOptionB(voteEmp.getOptionB()); - xxpf.setOptionC(voteEmp.getOptionC()); - xxpf.setOptionD(voteEmp.getOptionD()); - xxpf.setAvgScore(voteEmp.getAvgScore()); - xxpf.setPercentage(voteEmp.getPercentage()); - votesDatas.put("khx"+index2, xxpf); - sumScore = sumScore.add(voteEmp.getEndScore()); - if (index1 == 1) { - List children3 = new ArrayList<>(); - JSONObject child1 = new JSONObject(); - JSONObject child2 = new JSONObject(); - JSONObject child3 = new JSONObject(); - JSONObject child4 = new JSONObject(); - JSONObject child5 = new JSONObject(); - JSONObject child6 = new JSONObject(); - child1.put("name", "optionA"); - child1.put("label", "优秀"); - child2.put("name", "optionB"); - child2.put("label", "合格"); - child3.put("name", "optionC"); - child3.put("label", "基本合格"); - child4.put("name", "optionD"); - child4.put("label", "不合格"); - child5.put("name", "avgScore"); - child5.put("label", "得分"); - child6.put("name", "percentage"); - child6.put("label", "占比"); - children3.add(child1); - children3.add(child2); - children3.add(child3); - children3.add(child4); - children3.add(child5); - children3.add(child6); - tabledata.put("children", children3); - children2.add(tabledata); - } - } else if (voteEmp.getKhitemTypeid().equals(2L)) {//评分占比 - votesDatas.put("khx"+index2, voteEmp.getAvgScore()); - votesDatas.put("khx"+index2+"_zb", voteEmp.getPercentage()); - sumScore = sumScore.add(voteEmp.getEndScore()); - - if (index1 == 1) { - JSONObject tabledata2 = new JSONObject(); - tabledata2.put("name", "khx"+index2 + "_zb"); - tabledata2.put("label", "占比"); - children2.add(tabledata); - children2.add(tabledata2); - } - } else {//单独评分 - sumScore = sumScore.add(voteEmp.getAvgScore()); - votesDatas.put("khx"+index2, voteEmp.getAvgScore()); - if (index1 == 1) { - children2.add(tabledata); - } - } - } - pcdata.put("khdx", key); - pcdata.put(pyPCtitle, votesDatas); - pcdata.put(pyPCtitle+"_df", sumScore); - endData.add(pcdata); - - if (index1 == 1) { - tableColumn2.put("children", children2); - } - } - - children.add(tableColumn2); - JSONObject tableColumn3 = new JSONObject(); - tableColumn3.put("name", pyPCtitle+"_df"); - tableColumn3.put("label", "得分"); - children.add(tableColumn3); - //headerData.put("children", children); - //header.add(children); - - KhKhrwResult pcResult = new KhKhrwResult(); - pcResult.setPcId(pc.getId()); - pcResult.setPcName(pc.getPcTitle()); - pcResult.setTableHeader(children.toJSONString()); - pcResult.setTableData(endData.toJSONString()); - khKhrwResultService.insertKhKhrwResult(pcResult); - return AjaxResult.success(); + return khKhrwResultService.generateResult(pc); } /** diff --git a/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/service/IKhKhrwResultService.java b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/service/IKhKhrwResultService.java index fbefebe..06d5601 100644 --- a/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/service/IKhKhrwResultService.java +++ b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/service/IKhKhrwResultService.java @@ -1,7 +1,10 @@ package com.ruoyi.kaohe.service; import java.util.List; + +import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.kaohe.domain.KhKhrwResult; +import com.ruoyi.kaohe.domain.KhPingce; /** * 考核结果Service接口 @@ -58,4 +61,6 @@ public interface IKhKhrwResultService * @return 结果 */ public int deleteKhKhrwResultById(Long id); + + AjaxResult generateResult(KhPingce pc); } diff --git a/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/service/impl/KhKhrwResultServiceImpl.java b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/service/impl/KhKhrwResultServiceImpl.java index 898aa2e..1ba078a 100644 --- a/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/service/impl/KhKhrwResultServiceImpl.java +++ b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/service/impl/KhKhrwResultServiceImpl.java @@ -1,11 +1,20 @@ package com.ruoyi.kaohe.service.impl; -import java.util.List; +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.kaohe.domain.*; +import com.ruoyi.kaohe.mapper.KhVoteEmpMapper; +import com.ruoyi.kaohe.mapper.KhVoteMapper; +import com.ruoyi.kaohe.util.PinYinUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ruoyi.kaohe.mapper.KhKhrwResultMapper; -import com.ruoyi.kaohe.domain.KhKhrwResult; import com.ruoyi.kaohe.service.IKhKhrwResultService; /** @@ -19,6 +28,10 @@ public class KhKhrwResultServiceImpl implements IKhKhrwResultService { @Autowired private KhKhrwResultMapper khKhrwResultMapper; + @Autowired + private KhVoteMapper khVoteMapper; + @Autowired + private KhVoteEmpMapper khVoteEmpMapper; /** * 查询考核结果 @@ -93,4 +106,151 @@ public class KhKhrwResultServiceImpl implements IKhKhrwResultService { return khKhrwResultMapper.deleteKhKhrwResultById(id); } + + @Override + public AjaxResult generateResult(KhPingce pc) { + JSONArray children = new JSONArray(); + JSONObject tableColumn = new JSONObject(); + tableColumn.put("name", "khdx"); + if (pc.getBkhdxType().equals("0")) { + tableColumn.put("label", "单位"); + } else { + tableColumn.put("label", "姓名"); + } + children.add(tableColumn); + + JSONObject tableColumn2 = new JSONObject(); + String pyPCtitle = PinYinUtil.getPinyinInitials(pc.getPcTitle()); + tableColumn2.put("name", pyPCtitle); + tableColumn2.put("label", pc.getPcTitle()); + +//----------------------------------------------------------------------------------------- + + JSONArray endData = new JSONArray(); //存放表格数据 + List lists = new ArrayList<>(); + + KhVote khVote = new KhVote(); + khVote.setPingceId(pc.getId()); + //查询该考核任务下的所有评分任务 + List votes = khVoteMapper.selectKhVoteList(khVote); + for (KhVote vote : votes) { + KhVoteEmp khVoteEmp = new KhVoteEmp(); + khVoteEmp.setVoteId(vote.getId()); + //查询该评分任务对应的所有被考核对象详情 + List khVoteEmps = khVoteEmpMapper.selectKhVoteEmpList(khVoteEmp); + lists.addAll(khVoteEmps); + } + //根据被考核对象名分组数据到map中 + Map> khdxMap = lists.stream() + .collect(Collectors.groupingBy(KhVoteEmp::getBkhdxName, + LinkedHashMap::new, // 使用LinkedHashMap保持插入顺序(这对于键很重要) + Collectors.toList())); // 根据getBkhdxName分组*/lists.stream(). + //循环map得到对应数据 + Set>> entries = khdxMap.entrySet(); + Integer index1=0; + for (Map.Entry> entry : entries) { + index1++; + BigDecimal sumScore = BigDecimal.ZERO; + String key = entry.getKey(); + //获取表头数据 + List children2 = new ArrayList<>(); +//------------------------------------------------------------------------------------------------------ + + //获取表数据 + JSONObject pcdata = new JSONObject(); + List value = entry.getValue(); + JSONObject votesDatas = new JSONObject(); + Integer index2 = 0; + for (KhVoteEmp voteEmp : value) { + index2++; + JSONObject tabledata = new JSONObject(); + tabledata.put("name", "khx"+index2); + tabledata.put("label", voteEmp.getVoteTitle()); + + Object objectData; + //根据考核类型存储不同数据 + if (voteEmp.getKhitemTypeid().equals(1L)) { //评分选项 + KhXxpf xxpf = new KhXxpf(); + xxpf.setOptionA(voteEmp.getOptionA()); + xxpf.setOptionB(voteEmp.getOptionB()); + xxpf.setOptionC(voteEmp.getOptionC()); + xxpf.setOptionD(voteEmp.getOptionD()); + xxpf.setAvgScore(voteEmp.getAvgScore()); + xxpf.setPercentage(voteEmp.getPercentage()); + votesDatas.put("khx"+index2, xxpf); + sumScore = sumScore.add(voteEmp.getEndScore()); + if (index1 == 1) { + List children3 = new ArrayList<>(); + JSONObject child1 = new JSONObject(); + JSONObject child2 = new JSONObject(); + JSONObject child3 = new JSONObject(); + JSONObject child4 = new JSONObject(); + JSONObject child5 = new JSONObject(); + JSONObject child6 = new JSONObject(); + child1.put("name", "optionA"); + child1.put("label", "优秀"); + child2.put("name", "optionB"); + child2.put("label", "合格"); + child3.put("name", "optionC"); + child3.put("label", "基本合格"); + child4.put("name", "optionD"); + child4.put("label", "不合格"); + child5.put("name", "avgScore"); + child5.put("label", "得分"); + child6.put("name", "percentage"); + child6.put("label", "占比"); + children3.add(child1); + children3.add(child2); + children3.add(child3); + children3.add(child4); + children3.add(child5); + children3.add(child6); + tabledata.put("children", children3); + children2.add(tabledata); + } + } else if (voteEmp.getKhitemTypeid().equals(2L)) {//评分占比 + votesDatas.put("khx"+index2, voteEmp.getAvgScore()); + votesDatas.put("khx"+index2+"_zb", voteEmp.getPercentage()); + sumScore = sumScore.add(voteEmp.getEndScore()); + + if (index1 == 1) { + JSONObject tabledata2 = new JSONObject(); + tabledata2.put("name", "khx"+index2 + "_zb"); + tabledata2.put("label", "占比"); + children2.add(tabledata); + children2.add(tabledata2); + } + } else {//单独评分 + sumScore = sumScore.add(voteEmp.getAvgScore()); + votesDatas.put("khx"+index2, voteEmp.getAvgScore()); + if (index1 == 1) { + children2.add(tabledata); + } + } + } + pcdata.put("khdx", key); + pcdata.put(pyPCtitle, votesDatas); + pcdata.put(pyPCtitle+"_df", sumScore); + endData.add(pcdata); + + if (index1 == 1) { + tableColumn2.put("children", children2); + } + } + + children.add(tableColumn2); + JSONObject tableColumn3 = new JSONObject(); + tableColumn3.put("name", pyPCtitle+"_df"); + tableColumn3.put("label", "得分"); + children.add(tableColumn3); + + + KhKhrwResult pcResult = new KhKhrwResult(); + pcResult.setPcId(pc.getId()); + pcResult.setPcName(pc.getPcTitle()); + pcResult.setTableHeader(children.toJSONString()); + pcResult.setTableData(endData.toJSONString()); + this.insertKhKhrwResult(pcResult); + return AjaxResult.success(); + } } diff --git a/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/service/impl/KhVoteEmpServiceImpl.java b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/service/impl/KhVoteEmpServiceImpl.java index 7c0f743..4d1eaf7 100644 --- a/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/service/impl/KhVoteEmpServiceImpl.java +++ b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/service/impl/KhVoteEmpServiceImpl.java @@ -159,6 +159,10 @@ public class KhVoteEmpServiceImpl implements IKhVoteEmpService { BigDecimal avgScore = (optionA.multiply(a).add(optionB.multiply(b).add(optionC.multiply(c).add(optionD.multiply(d))) )).divide(voteEmp.getVoteNum(),4, RoundingMode.HALF_UP); voteEmp.setAvgScore(avgScore);//投票后计算平均分 + voteEmp.setOptionA(optionA); + voteEmp.setOptionB(optionB); + voteEmp.setOptionC(optionC); + voteEmp.setOptionD(optionD); if (oldvoteEmp.getPercentage() != null) { //计算最后得分 voteEmp.setEndScore(avgScore.multiply(oldvoteEmp.getPercentage())); }else{ diff --git a/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/util/EnhancedJsonExporter.java b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/util/EnhancedJsonExporter.java new file mode 100644 index 0000000..bb395ed --- /dev/null +++ b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/util/EnhancedJsonExporter.java @@ -0,0 +1,299 @@ +package com.ruoyi.kaohe.util; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.util.IOUtils; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletResponse; +import java.util.*; + +public class EnhancedJsonExporter { + private static final Logger log = LoggerFactory.getLogger(EnhancedJsonExporter.class); + private static final ObjectMapper mapper = new ObjectMapper(); + + static class HeaderNode { + String name; + String label; + int level; + int startCol; + int span; + List children = new ArrayList<>(); + } + + //public static void exportWithMergedHeader(String jsonStr,String jsonData, String outputPath) throws Exception { + public static void exportWithMergedHeader(String jsonStr,String jsonData, HttpServletResponse response) throws Exception { + JsonNode rootNode = mapper.readTree(jsonStr); + JsonNode dataNode = mapper.readTree(jsonData); + Workbook workbook = new XSSFWorkbook(); + Sheet sheet = workbook.createSheet("sheet1"); + + //获取标题样式 + CellStyle headStyle = getStyle(workbook); + + // 构建表头树 + HeaderNode rootHeader = buildHeaderTree(rootNode, 0); + + // 计算列位置和跨度 + calculateHeaderLayout(rootHeader, 0); + + // 创建合并表头 + createMergedHeaderRows(sheet, rootHeader, headStyle); + + // 填充数据 + fillDataRows(sheet, dataNode, rootHeader,headStyle); + + // 自适应列宽 + autoSizeColumns(sheet, rootHeader.span); + + // 添加边框 + addBordersWithMergedRegions(sheet); + + // 输出文件 ——main方法测试该工具类时使用 + /*try (FileOutputStream fos = new FileOutputStream(outputPath)) { + workbook.write(fos); + }*/ + + //导出数据 + try + { + workbook.write(response.getOutputStream()); + } + catch (Exception e) + { + log.error("导出Excel异常{}", e.getMessage()); + } + finally + { + IOUtils.closeQuietly(workbook); + } + } + + private static HeaderNode buildHeaderTree(JsonNode node, int curLevel) { + HeaderNode root = new HeaderNode(); + if (node.isArray()) { + for (JsonNode child : node) { + root.children.add(buildHeaderTree(child, curLevel)); + } + return root; + } + + HeaderNode current = new HeaderNode(); + current.level = curLevel; + current.name = node.path("name").asText(); + current.label = node.path("label").asText(); + + if (node.has("children")) { + for (JsonNode child : node.path("children")) { + HeaderNode childNode = buildHeaderTree(child, curLevel + 1); + childNode.level = current.level + 1; + current.children.add(childNode); + } + } + return current; + } + + private static int calculateHeaderLayout(HeaderNode node, int startCol) { + if (node.children.isEmpty()) { + node.startCol = startCol; + node.span = 1; + return startCol + 1; + } + + int currentCol = startCol; + for (HeaderNode child : node.children) { + currentCol = calculateHeaderLayout(child, currentCol); + } + node.startCol = node.children.get(0).startCol; + node.span = currentCol - startCol; + return currentCol; + } + + private static int getMaxDepth(HeaderNode node) { + int max = node.level; + for (HeaderNode child : node.children) { + max = Math.max(max, getMaxDepth(child)); + } + return max; + } + + private static void createMergedHeaderRows(Sheet sheet, HeaderNode root, CellStyle headStyle) { + int maxDepth = getMaxDepth(root); + for (int level = 0; level <= maxDepth; level++) { + Row row = sheet.createRow(level); + createHeaderRow(sheet, row, root, level, headStyle, getMaxDepth(root)); + } + } + + //创建标题行 + private static void createHeaderRow(Sheet sheet, Row row, HeaderNode node, int targetLevel, CellStyle headStyle, int maxLevel) { + if (node.name!=null&&node.level == targetLevel) { + Cell cell = row.createCell(node.startCol); + cell.setCellValue(node.label); + cell.setCellStyle(headStyle); + // 列合并处理 + if (node.span > 1) { + sheet.addMergedRegion(new CellRangeAddress( + row.getRowNum(), row.getRowNum(), + node.startCol, node.startCol + node.span - 1 + )); + } + // 行合并(关键改进点) + if (shouldMergeRows(node, maxLevel)) { + sheet.addMergedRegion(new CellRangeAddress( + row.getRowNum(), maxLevel, + node.startCol, node.startCol + )); + } + return; + } + for (HeaderNode child : node.children) { + createHeaderRow(sheet, row, child, targetLevel, headStyle, maxLevel); + } + } + + private static boolean shouldMergeRows(HeaderNode node, int maxLevel) { + // 当前节点没有子节点 且 不是最后一级 + return node.children.isEmpty() && node.level < maxLevel; + } + + //设置字体样式 + private static CellStyle getStyle(Workbook workbook) { + CellStyle style = workbook.createCellStyle(); + style.setWrapText(true); // 启用自动换行 + // 设置水平居中 + style.setAlignment(HorizontalAlignment.CENTER); + // 设置垂直居中 + style.setVerticalAlignment(VerticalAlignment.CENTER); + Font font = workbook.createFont(); + // 设置加粗 + // font.setBold(true); + // 设置字号 + font.setFontHeightInPoints((short) 12); + //设置字体 + // font.setFontName("宋体"); + // 将字体应用到样式 + style.setFont(font); + return style; + } + + private static void fillDataRows(Sheet sheet, JsonNode dataNode, HeaderNode header, CellStyle style) { + if (!dataNode.isArray()) return; + int startRow = getMaxDepth(header) + 1; + for (int i = 0; i < dataNode.size(); i++) { + Row row = sheet.createRow(startRow + i); + fillRowData(row, dataNode.get(i), header, style); + } + } + + private static void fillRowData(Row row, JsonNode data, HeaderNode header, CellStyle style) { + if (header.children.isEmpty()) { + if (data.has(header.name)) { + Cell cell = row.createCell(header.startCol); + cell.setCellValue(data.get(header.name).asText()); + cell.setCellStyle(style); + } + return; + } + + for (HeaderNode child : header.children) { + if (header.name!=null&&data.has(header.name)) { + data=data.get(header.name); + } + fillRowData(row, data, child, style); + } + } + + + private static void autoSizeColumns(Sheet sheet, int columnCount) { + for (int i = 0; i < columnCount; i++) { + sheet.autoSizeColumn(i, true); + // sheet.setColumnWidth(i, sheet.getColumnWidth(i) + 6 * 256); //中文自动列宽不准确,这里4*256 代表额外增加4个中文字符宽度 + sheet.setColumnWidth(i, sheet.getColumnWidth(i)); + } + } + + public static void addBordersWithMergedRegions(Sheet sheet) { + // 创建细线边框样式 + CellStyle borderStyle = createBorderStyle(sheet.getWorkbook()); + + // 先处理合并区域边框 + for (int i = 0; i < sheet.getNumMergedRegions(); i++) { + CellRangeAddress region = sheet.getMergedRegion(i); + applyBorderToMergedRegion(sheet, region, borderStyle); + } + + // 再处理普通单元格边框 + for (Row row : sheet) { + for (Cell cell : row) { + if (!isInMergedRegion(cell, sheet)) { + applyBorderToCell(cell, borderStyle); + } + } + } + } + + private static CellStyle createBorderStyle(Workbook workbook) { + CellStyle style = workbook.createCellStyle(); + style.setBorderTop(BorderStyle.THIN); + style.setBorderBottom(BorderStyle.THIN); + style.setBorderLeft(BorderStyle.THIN); + style.setBorderRight(BorderStyle.THIN); + return style; + } + + private static void applyBorderToMergedRegion(Sheet sheet, + CellRangeAddress region, CellStyle style) { + for (int rowNum = region.getFirstRow(); rowNum <= region.getLastRow(); rowNum++) { + Row row = sheet.getRow(rowNum) != null ? sheet.getRow(rowNum) : sheet.createRow(rowNum); + for (int colNum = region.getFirstColumn(); colNum <= region.getLastColumn(); colNum++) { + Cell cell = row.getCell(colNum) != null ? row.getCell(colNum) : row.createCell(colNum); + CellStyle newStyle = sheet.getWorkbook().createCellStyle(); + newStyle.cloneStyleFrom(cell.getCellStyle()); + newStyle.setBorderTop(BorderStyle.THIN); + newStyle.setBorderBottom(BorderStyle.THIN); + newStyle.setBorderLeft(BorderStyle.THIN); + newStyle.setBorderRight(BorderStyle.THIN); + cell.setCellStyle(newStyle); + } + } + } + + private static boolean isInMergedRegion(Cell cell, Sheet sheet) { + for (int i = 0; i < sheet.getNumMergedRegions(); i++) { + CellRangeAddress region = sheet.getMergedRegion(i); + if (region.isInRange(cell.getRowIndex(), cell.getColumnIndex())) { + return true; + } + } + return false; + } + + private static void applyBorderToCell(Cell cell, CellStyle style) { + CellStyle newStyle = cell.getSheet().getWorkbook().createCellStyle(); + newStyle.cloneStyleFrom(cell.getCellStyle()); + newStyle.setBorderTop(style.getBorderTop()); + newStyle.setBorderBottom(style.getBorderBottom()); + newStyle.setBorderLeft(style.getBorderLeft()); + newStyle.setBorderRight(style.getBorderRight()); + cell.setCellStyle(newStyle); + } + + public static void main(String[] args) { + String jsonHead = "[{\"children\":[{\"name\":\"khdx\",\"label\":\"单位\"},{\"children\":[{\"children\":[{\"name\":\"khx1\",\"label\":\"政治建设\"},{\"name\":\"khx1_zb\",\"label\":\"占比\"},{\"name\":\"khx2\",\"label\":\"宣传与思想政治工作\"},{\"name\":\"khx2_zb\",\"label\":\"占比\"},{\"name\":\"khx3\",\"label\":\"作风纪律\"},{\"name\":\"khx3_zb\",\"label\":\"占比\"},{\"name\":\"khx4\",\"label\":\"安全稳定\"},{\"name\":\"khx4_zb\",\"label\":\"占比\"},{\"name\":\"khx5\",\"label\":\"师资队伍与师德师风\"},{\"name\":\"khx5_zb\",\"label\":\"占比\"},{\"name\":\"khx6\",\"label\":\"财务工作\"},{\"name\":\"khx6_zb\",\"label\":\"占比\"},{\"name\":\"khx7\",\"label\":\"依法治校与综合治理\"},{\"name\":\"khx7_zb\",\"label\":\"占比\"},{\"name\":\"khx8\",\"label\":\"国有资产管理\"},{\"name\":\"khx8_zb\",\"label\":\"占比\"},{\"name\":\"khx9\",\"label\":\"实验室管理\"},{\"name\":\"khx9_zb\",\"label\":\"占比\"},{\"name\":\"khx10\",\"label\":\"招生就业与创新创业工作\"},{\"name\":\"khx10_zb\",\"label\":\"占比\"},{\"name\":\"khx11\",\"label\":\"对外交流与合作\"},{\"name\":\"khx11_zb\",\"label\":\"占比\"}],\"name\":\"djyxzmbrw\",\"label\":\"党建与行政目标任务\"},{\"name\":\"djyxzmbrw_df\",\"label\":\"得分\"},{\"name\":\"djyxzmbrw_zb\",\"label\":\"占比\"},{\"name\":\"djyxzmbrw_zsfs\",\"label\":\"折算分数\"},{\"children\":[{\"name\":\"khx1\",\"label\":\"教学工作\"},{\"name\":\"khx1_zb\",\"label\":\"占比\"},{\"name\":\"khx2\",\"label\":\"科研工作\"},{\"name\":\"khx2_zb\",\"label\":\"占比\"},{\"name\":\"khx3\",\"label\":\"学生工作\"},{\"name\":\"khx3_zb\",\"label\":\"占比\"}],\"name\":\"syfz\",\"label\":\"事业发展\"},{\"name\":\"syfz_df\",\"label\":\"得分\"},{\"name\":\"syfz_zb\",\"label\":\"占比\"},{\"name\":\"syfz_zsfs\",\"label\":\"折算分数\"}],\"name\":\"ejbt\",\"label\":\"二级标题\"},{\"name\":\"ejbt_df\",\"label\":\"得分\"},{\"name\":\"ejbt_zb\",\"label\":\"占比\"},{\"name\":\"ejbt_zsfs\",\"label\":\"折算分数\"},{\"children\":[{\"children\":[{\"name\":\"optionA\",\"label\":\"优秀\"},{\"name\":\"optionB\",\"label\":\"合格\"},{\"name\":\"optionC\",\"label\":\"基本合格\"},{\"name\":\"optionD\",\"label\":\"不合格\"},{\"name\":\"avgScore\",\"label\":\"得分\"},{\"name\":\"percentage\",\"label\":\"占比\"}],\"name\":\"khx1\",\"label\":\"师院领导班子\"},{\"children\":[{\"name\":\"optionA\",\"label\":\"优秀\"},{\"name\":\"optionB\",\"label\":\"合格\"},{\"name\":\"optionC\",\"label\":\"基本合格\"},{\"name\":\"optionD\",\"label\":\"不合格\"},{\"name\":\"avgScore\",\"label\":\"得分\"},{\"name\":\"percentage\",\"label\":\"占比\"}],\"name\":\"khx2\",\"label\":\"师院处级领导干部\"},{\"children\":[{\"name\":\"optionA\",\"label\":\"优秀\"},{\"name\":\"optionB\",\"label\":\"合格\"},{\"name\":\"optionC\",\"label\":\"基本合格\"},{\"name\":\"optionD\",\"label\":\"不合格\"},{\"name\":\"avgScore\",\"label\":\"得分\"},{\"name\":\"percentage\",\"label\":\"占比\"}],\"name\":\"khx3\",\"label\":\"服务对象代表\"}],\"name\":\"mzcp\",\"label\":\"民主测评\"},{\"name\":\"mzcp_df\",\"label\":\"得分\"},{\"name\":\"mzcp_zb\",\"label\":\"占比\"},{\"name\":\"mzcp_zsfs\",\"label\":\"折算分数\"},{\"children\":[{\"name\":\"khx1\",\"label\":\"分数 (满分10分)\"}],\"name\":\"tscx\",\"label\":\"特色创新\"},{\"name\":\"tscx_df\",\"label\":\"得分\"},{\"name\":\"tscx_zb\",\"label\":\"占比\"},{\"name\":\"tscx_zsfs\",\"label\":\"折算分数\"},{\"name\":\"cssj1_df\",\"label\":\"总分\"}],\"name\":\"cssj1\",\"label\":\"测试数据1\"}]"; // 替换为实际JSON字符串 + String jsonData = "[{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":10},\"khdx\":\"物理科学与技术学院\",\"mzcp_zsfs\":73.6,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx2\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx3\":{\"avgScore\":80,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":2}},\"ejbt_zsfs\":9.8866,\"mzcp_zb\":0.8,\"tscx_df\":10,\"ejbt_df\":98.866,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":89.001,\"djyxzmbrw_df\":98.65,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":100,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":90,\"khx3_zb\":0.1,\"khx6\":100,\"khx3\":100,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":99,\"khx10\":100,\"khx8\":100,\"khx11\":100,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.865,\"syfz_df\":98.89,\"syfz\":{\"khx1\":100,\"khx1_zb\":0.5,\"khx2\":98,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":97.5}},\"mzcp_df\":92,\"tscx_zsfs\":1,\"cssj1_df\":84.4866}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":10},\"khdx\":\"体育系\",\"mzcp_zsfs\":65.6,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":80,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":1},\"khx2\":{\"avgScore\":60,\"percentage\":0.3,\"optionC\":1,\"optionD\":0,\"optionA\":0,\"optionB\":0},\"khx3\":{\"avgScore\":100,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":2,\"optionB\":0}},\"ejbt_zsfs\":9.3547,\"mzcp_zb\":0.8,\"tscx_df\":10,\"ejbt_df\":93.547,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":83.997,\"djyxzmbrw_df\":95.5,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":85,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":100,\"khx3_zb\":0.1,\"khx6\":100,\"khx3\":98,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":100,\"khx10\":100,\"khx8\":100,\"khx11\":90,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.55,\"syfz_df\":93.33,\"syfz\":{\"khx1\":89,\"khx1_zb\":0.5,\"khx2\":97,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":98.5}},\"mzcp_df\":82,\"tscx_zsfs\":1,\"cssj1_df\":75.9547}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":10},\"khdx\":\"外国语学院\",\"mzcp_zsfs\":75.2,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":80,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":1},\"khx2\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx3\":{\"avgScore\":100,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":2,\"optionB\":0}},\"ejbt_zsfs\":9.8069,\"mzcp_zb\":0.8,\"tscx_df\":10,\"ejbt_df\":98.069,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":88.605,\"djyxzmbrw_df\":94.64,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":90,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":100,\"khx3_zb\":0.1,\"khx6\":96,\"khx3\":90,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":90,\"khx10\":100,\"khx8\":97,\"khx11\":89,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.464,\"syfz_df\":98.45,\"syfz\":{\"khx1\":100,\"khx1_zb\":0.5,\"khx2\":98,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":95.5}},\"mzcp_df\":94,\"tscx_zsfs\":1,\"cssj1_df\":86.0069}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":7.5},\"khdx\":\"生命科学系\",\"mzcp_zsfs\":68.8,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx2\":{\"avgScore\":80,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":1},\"khx3\":{\"avgScore\":80,\"percentage\":0.4,\"optionC\":1,\"optionD\":0,\"optionA\":1,\"optionB\":0}},\"ejbt_zsfs\":9.7226,\"mzcp_zb\":0.8,\"tscx_df\":7.5,\"ejbt_df\":97.226,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":87.453,\"djyxzmbrw_df\":97.73,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":96,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":100,\"khx3_zb\":0.1,\"khx6\":99,\"khx3\":99,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":99,\"khx10\":96,\"khx8\":99,\"khx11\":95,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.773,\"syfz_df\":97.17,\"syfz\":{\"khx1\":95,\"khx1_zb\":0.5,\"khx2\":100,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":98.5}},\"mzcp_df\":86,\"tscx_zsfs\":0.75,\"cssj1_df\":79.2726}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":10},\"khdx\":\"化学系\",\"mzcp_zsfs\":73.6,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx2\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx3\":{\"avgScore\":80,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":2}},\"ejbt_zsfs\":9.2434,\"mzcp_zb\":0.8,\"tscx_df\":10,\"ejbt_df\":92.434,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":82.899,\"djyxzmbrw_df\":95.35,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":86,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":100,\"khx3_zb\":0.1,\"khx6\":99,\"khx3\":94,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":99,\"khx10\":100,\"khx8\":100,\"khx11\":92,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.535,\"syfz_df\":92.11,\"syfz\":{\"khx1\":87,\"khx1_zb\":0.5,\"khx2\":97,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":97.5}},\"mzcp_df\":92,\"tscx_zsfs\":1,\"cssj1_df\":83.8434}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":7.5},\"khdx\":\"文学院\",\"mzcp_zsfs\":70.4,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":80,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":1},\"khx2\":{\"avgScore\":80,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":1},\"khx3\":{\"avgScore\":100,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":2,\"optionB\":0}},\"ejbt_zsfs\":9.0252,\"mzcp_zb\":0.8,\"tscx_df\":7.5,\"ejbt_df\":90.252,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":80.604,\"djyxzmbrw_df\":96.48,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":90,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":100,\"khx3_zb\":0.1,\"khx6\":100,\"khx3\":99,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":90,\"khx10\":100,\"khx8\":99,\"khx11\":94,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.648,\"syfz_df\":89.56,\"syfz\":{\"khx1\":83,\"khx1_zb\":0.5,\"khx2\":97,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":95}},\"mzcp_df\":88,\"tscx_zsfs\":0.75,\"cssj1_df\":80.1752}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":10},\"khdx\":\"继续教育学院\",\"mzcp_zsfs\":80,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx2\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx3\":{\"avgScore\":100,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":2,\"optionB\":0}},\"ejbt_zsfs\":8.8449,\"mzcp_zb\":0.8,\"tscx_df\":10,\"ejbt_df\":88.449,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":78.759,\"djyxzmbrw_df\":96.9,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":90,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":100,\"khx3_zb\":0.1,\"khx6\":99,\"khx3\":98,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":100,\"khx10\":100,\"khx8\":100,\"khx11\":95,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.69,\"syfz_df\":87.51,\"syfz\":{\"khx1\":80,\"khx1_zb\":0.5,\"khx2\":97,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":92.5}},\"mzcp_df\":100,\"tscx_zsfs\":1,\"cssj1_df\":89.8449}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":10},\"khdx\":\"教育学院\",\"mzcp_zsfs\":64,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":80,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":1},\"khx2\":{\"avgScore\":80,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":1},\"khx3\":{\"avgScore\":80,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":2}},\"ejbt_zsfs\":9.4026,\"mzcp_zb\":0.8,\"tscx_df\":10,\"ejbt_df\":94.026,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":84.546,\"djyxzmbrw_df\":94.8,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":90,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":88,\"khx3_zb\":0.1,\"khx6\":93,\"khx3\":100,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":100,\"khx10\":99,\"khx8\":100,\"khx11\":91,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.48,\"syfz_df\":93.94,\"syfz\":{\"khx1\":90,\"khx1_zb\":0.5,\"khx2\":97,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":99}},\"mzcp_df\":80,\"tscx_zsfs\":1,\"cssj1_df\":74.4026}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":10},\"khdx\":\"美术学院\",\"mzcp_zsfs\":73.6,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx2\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx3\":{\"avgScore\":80,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":2}},\"ejbt_zsfs\":8.9429,\"mzcp_zb\":0.8,\"tscx_df\":10,\"ejbt_df\":89.429,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":79.749,\"djyxzmbrw_df\":96.8,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":90,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":100,\"khx3_zb\":0.1,\"khx6\":99,\"khx3\":98,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":100,\"khx10\":100,\"khx8\":100,\"khx11\":94,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.68,\"syfz_df\":88.61,\"syfz\":{\"khx1\":80,\"khx1_zb\":0.5,\"khx2\":97,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":97.5}},\"mzcp_df\":92,\"tscx_zsfs\":1,\"cssj1_df\":83.5429}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":10},\"khdx\":\"海洋学院\",\"mzcp_zsfs\":64,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":80,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":1},\"khx2\":{\"avgScore\":80,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":1},\"khx3\":{\"avgScore\":80,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":2}},\"ejbt_zsfs\":8.9428,\"mzcp_zb\":0.8,\"tscx_df\":10,\"ejbt_df\":89.428,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":80.1,\"djyxzmbrw_df\":93.28,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":96,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":80,\"khx3_zb\":0.1,\"khx6\":90,\"khx3\":90,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":100,\"khx10\":94,\"khx8\":99,\"khx11\":90,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.328,\"syfz_df\":89,\"syfz\":{\"khx1\":80,\"khx1_zb\":0.5,\"khx2\":98,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":98}},\"mzcp_df\":80,\"tscx_zsfs\":1,\"cssj1_df\":73.9428}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":9},\"khdx\":\"音乐系\",\"mzcp_zsfs\":75.2,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":80,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":1},\"khx2\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx3\":{\"avgScore\":100,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":2,\"optionB\":0}},\"ejbt_zsfs\":8.8475,\"mzcp_zb\":0.8,\"tscx_df\":9,\"ejbt_df\":88.475,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":78.912,\"djyxzmbrw_df\":95.63,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":90,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":100,\"khx3_zb\":0.1,\"khx6\":99,\"khx3\":97,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":89,\"khx10\":100,\"khx8\":99,\"khx11\":89,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.563,\"syfz_df\":87.68,\"syfz\":{\"khx1\":80,\"khx1_zb\":0.5,\"khx2\":98,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":92}},\"mzcp_df\":94,\"tscx_zsfs\":0.9,\"cssj1_df\":84.9475}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":5},\"khdx\":\"历史文化与法学系\",\"mzcp_zsfs\":73.6,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx2\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx3\":{\"avgScore\":80,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":2}},\"ejbt_zsfs\":8.8914,\"mzcp_zb\":0.8,\"tscx_df\":5,\"ejbt_df\":88.914,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":79.308,\"djyxzmbrw_df\":96.06,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":100,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":80,\"khx3_zb\":0.1,\"khx6\":99,\"khx3\":98,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":96,\"khx10\":100,\"khx8\":93,\"khx11\":90,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.606,\"syfz_df\":88.12,\"syfz\":{\"khx1\":80,\"khx1_zb\":0.5,\"khx2\":98,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":94}},\"mzcp_df\":92,\"tscx_zsfs\":0.5,\"cssj1_df\":82.9914}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":10},\"khdx\":\"数学与计算科学学院\",\"mzcp_zsfs\":75.2,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":80,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":1},\"khx2\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx3\":{\"avgScore\":100,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":2,\"optionB\":0}},\"ejbt_zsfs\":9.1797,\"mzcp_zb\":0.8,\"tscx_df\":10,\"ejbt_df\":91.797,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":82.215,\"djyxzmbrw_df\":95.82,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":90,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":100,\"khx3_zb\":0.1,\"khx6\":100,\"khx3\":100,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":96,\"khx10\":94,\"khx8\":96,\"khx11\":90,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.582,\"syfz_df\":91.35,\"syfz\":{\"khx1\":88,\"khx1_zb\":0.5,\"khx2\":98,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":90.5}},\"mzcp_df\":94,\"tscx_zsfs\":1,\"cssj1_df\":85.3797}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":10},\"khdx\":\"计算机科学技术系\",\"mzcp_zsfs\":64,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx2\":{\"avgScore\":60,\"percentage\":0.3,\"optionC\":1,\"optionD\":0,\"optionA\":0,\"optionB\":0},\"khx3\":{\"avgScore\":80,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":2}},\"ejbt_zsfs\":8.9912,\"mzcp_zb\":0.8,\"tscx_df\":10,\"ejbt_df\":89.912,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":80.298,\"djyxzmbrw_df\":96.14,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":90,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":100,\"khx3_zb\":0.1,\"khx6\":97,\"khx3\":98,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":100,\"khx7\":100,\"khx10\":100,\"khx8\":97,\"khx11\":87,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.614,\"syfz_df\":89.22,\"syfz\":{\"khx1\":80,\"khx1_zb\":0.5,\"khx2\":98,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":99}},\"mzcp_df\":80,\"tscx_zsfs\":1,\"cssj1_df\":73.9912}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":10},\"khdx\":\"资源管理系\",\"mzcp_zsfs\":68.8,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx2\":{\"avgScore\":80,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":1},\"khx3\":{\"avgScore\":80,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":2}},\"ejbt_zsfs\":9.5029,\"mzcp_zb\":0.8,\"tscx_df\":10,\"ejbt_df\":95.029,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":85.536,\"djyxzmbrw_df\":94.93,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":88,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":100,\"khx3_zb\":0.1,\"khx6\":95,\"khx3\":98,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":99,\"khx10\":100,\"khx8\":99,\"khx11\":84,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.493,\"syfz_df\":95.04,\"syfz\":{\"khx1\":99,\"khx1_zb\":0.5,\"khx2\":99,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":81}},\"mzcp_df\":86,\"tscx_zsfs\":1,\"cssj1_df\":79.3029}},{\"cssj1\":{\"ejbt_zb\":0.1,\"tscx\":{\"khx1\":10},\"khdx\":\"马克思主义学院\",\"mzcp_zsfs\":73.6,\"tscx_zb\":0.1,\"mzcp\":{\"khx1\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx2\":{\"avgScore\":100,\"percentage\":0.3,\"optionC\":0,\"optionD\":0,\"optionA\":1,\"optionB\":0},\"khx3\":{\"avgScore\":80,\"percentage\":0.4,\"optionC\":0,\"optionD\":0,\"optionA\":0,\"optionB\":2}},\"ejbt_zsfs\":8.701,\"mzcp_zb\":0.8,\"tscx_df\":10,\"ejbt_df\":87.01,\"ejbt\":{\"syfz_zb\":0.9,\"syfz_zsfs\":77.49,\"djyxzmbrw_df\":95.2,\"djyxzmbrw\":{\"khx9_zb\":0.03,\"khx8_zb\":0.02,\"khx7_zb\":0.05,\"khx1\":90,\"khx2\":100,\"khx4_zb\":0.1,\"khx5\":100,\"khx3_zb\":0.1,\"khx6\":100,\"khx3\":94,\"khx5_zb\":0.1,\"khx4\":100,\"khx6_zb\":0.1,\"khx9\":90,\"khx7\":100,\"khx10\":97,\"khx8\":100,\"khx11\":84,\"khx1_zb\":0.2,\"khx2_zb\":0.1,\"khx10_zb\":0.1,\"khx11_zb\":0.1},\"djyxzmbrw_zb\":0.1,\"djyxzmbrw_zsfs\":9.52,\"syfz_df\":86.1,\"syfz\":{\"khx1\":80,\"khx1_zb\":0.5,\"khx2\":90,\"khx2_zb\":0.28,\"khx3_zb\":0.22,\"khx3\":95}},\"mzcp_df\":92,\"tscx_zsfs\":1,\"cssj1_df\":83.301}}]"; + // String jsonHead ="[{\"name\":\"khdx\",\"label\":\"单位\"},{\"name\":\"tscx\",\"label\":\"特色创新\",\"children\":[{\"name\":\"khx1\",\"label\":\"分数 (满分10分)\"}]},{\"name\":\"tscx_df\",\"label\":\"得分\"}]"; + // String jsonData ="[{\"khdx\":\"生命科学系\",\"tscx\":{\"khx1\":7.5000},\"tscx_df\":7.5000},{\"khdx\":\"海洋学院\",\"tscx\":{\"khx1\":10.0000},\"tscx_df\":10.0000},{\"khdx\":\"历史文化与法学系\",\"tscx\":{\"khx1\":5.0000},\"tscx_df\":5.0000},{\"khdx\":\"物理科学与技术学院\",\"tscx\":{\"khx1\":10.0000},\"tscx_df\":10.0000},{\"khdx\":\"教育学院\",\"tscx\":{\"khx1\":10.0000},\"tscx_df\":10.0000},{\"khdx\":\"资源管理系\",\"tscx\":{\"khx1\":10.0000},\"tscx_df\":10.0000},{\"khdx\":\"马克思主义学院\",\"tscx\":{\"khx1\":10.0000},\"tscx_df\":10.0000},{\"khdx\":\"美术学院\",\"tscx\":{\"khx1\":10.0000},\"tscx_df\":10.0000},{\"khdx\":\"计算机科学技术系\",\"tscx\":{\"khx1\":10.0000},\"tscx_df\":10.0000},{\"khdx\":\"化学系\",\"tscx\":{\"khx1\":10.0000},\"tscx_df\":10.0000},{\"khdx\":\"数学与计算科学学院\",\"tscx\":{\"khx1\":10.0000},\"tscx_df\":10.0000},{\"khdx\":\"继续教育学院\",\"tscx\":{\"khx1\":10.0000},\"tscx_df\":10.0000},{\"khdx\":\"外国语学院\",\"tscx\":{\"khx1\":10.0000},\"tscx_df\":10.0000},{\"khdx\":\"体育系\",\"tscx\":{\"khx1\":10.0000},\"tscx_df\":10.0000},{\"khdx\":\"文学院\",\"tscx\":{\"khx1\":7.5000},\"tscx_df\":7.5000},{\"khdx\":\"音乐系\",\"tscx\":{\"khx1\":9.0000},\"tscx_df\":9.0000}]"; + try { + //main方法测试时去掉方法中的response参数,使用本地导出测试 + // exportWithMergedHeader(jsonHead,jsonData, "考核结果.xlsx"); + System.out.println("导出成功"); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/util/JsonDeepMerge.java b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/util/JsonDeepMerge.java index b486dd4..fe25882 100644 --- a/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/util/JsonDeepMerge.java +++ b/ruoyi-kaohe/src/main/java/com/ruoyi/kaohe/util/JsonDeepMerge.java @@ -31,7 +31,7 @@ public class JsonDeepMerge { } } } - + //根据某个相同key值,整合其他相同层级的key数据到一起,然后返回新的JSONArray数据 public static JSONArray mergeByKey(JSONArray array, String mergeKey) { JSONArray result = new JSONArray(); for (int i = 0; i < array.length(); i++) { diff --git a/考核结果.xlsx b/考核结果.xlsx new file mode 100644 index 0000000..6411406 Binary files /dev/null and b/考核结果.xlsx differ diff --git a/考核结果1.xlsx b/考核结果1.xlsx new file mode 100644 index 0000000..35d729b Binary files /dev/null and b/考核结果1.xlsx differ