diff --git a/event_smart/src/main/java/com/njcn/product/event/devcie/mapper/mapping/PqLineMapper.xml b/event_smart/src/main/java/com/njcn/product/event/devcie/mapper/mapping/PqLineMapper.xml index 6ecb2c3..9949399 100644 --- a/event_smart/src/main/java/com/njcn/product/event/devcie/mapper/mapping/PqLineMapper.xml +++ b/event_smart/src/main/java/com/njcn/product/event/devcie/mapper/mapping/PqLineMapper.xml @@ -41,6 +41,7 @@ pq_line.name lineName, PQ_SUBVOLTAGE.SUBV_INDEX busBarId, PQ_SUBVOLTAGE.name busBarName, + PQ_SUBVOLTAGE.SCALE, pq_device.dev_index devId, pq_device.name devName, pq_device.Status runFlag, diff --git a/event_smart/src/main/java/com/njcn/product/event/report/controller/EasyPoiWordExportController.java b/event_smart/src/main/java/com/njcn/product/event/report/controller/EasyPoiWordExportController.java index 5de4cfa..fc4fdab 100644 --- a/event_smart/src/main/java/com/njcn/product/event/report/controller/EasyPoiWordExportController.java +++ b/event_smart/src/main/java/com/njcn/product/event/report/controller/EasyPoiWordExportController.java @@ -3,20 +3,25 @@ package com.njcn.product.event.report.controller; import com.njcn.common.pojo.annotation.OperateInfo; import com.njcn.common.pojo.enums.response.CommonResponseEnum; import com.njcn.common.pojo.response.HttpResult; +import com.njcn.product.event.devcie.pojo.po.PqGdCompany; import com.njcn.product.event.report.pojo.param.ReportExportParam; import com.njcn.product.event.report.service.EasyPoiWordExportService; import com.njcn.product.event.report.utils.WordTemplate; import com.njcn.product.event.transientes.pojo.param.LargeScreenCountParam; +import com.njcn.product.event.transientes.pojo.po.PqsDepts; +import com.njcn.product.event.transientes.service.PqsDeptsService; import com.njcn.web.controller.BaseController; import com.njcn.web.utils.HttpResultUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; +import java.util.List; /** * @Author: cdf @@ -32,7 +37,8 @@ public class EasyPoiWordExportController extends BaseController { private final EasyPoiWordExportService easyPoiWordExportService; - + @Autowired + private PqsDeptsService pqsDeptsService; @OperateInfo @PostMapping("/get") @ApiOperation("") @@ -46,4 +52,14 @@ public class EasyPoiWordExportController extends BaseController { // return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); } + @OperateInfo + @PostMapping("/getDept") + public HttpResult> getDept() { + String methodDescribe = getMethodDescribe("getDept"); + + List list = pqsDeptsService.lambdaQuery().eq(PqsDepts::getState, 1).list(); + + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, list, methodDescribe); + } + } diff --git a/event_smart/src/main/java/com/njcn/product/event/report/pojo/dto/BjCustomReportDTO.java b/event_smart/src/main/java/com/njcn/product/event/report/pojo/dto/BjCustomReportDTO.java index 878b0d7..b7a3bfd 100644 --- a/event_smart/src/main/java/com/njcn/product/event/report/pojo/dto/BjCustomReportDTO.java +++ b/event_smart/src/main/java/com/njcn/product/event/report/pojo/dto/BjCustomReportDTO.java @@ -2,6 +2,9 @@ package com.njcn.product.event.report.pojo.dto; import lombok.Data; +import java.util.List; +import java.util.Map; + /** * @Author: cdf * @CreateTime: 2025-09-24 @@ -43,4 +46,9 @@ public class BjCustomReportDTO { private Integer affectedUserCount; // 暂降区域说明(如“亦庄经济开发区、通州新城、中心城区”) private String areaContent; + + private List> event; + + private List> companyEvent; + } diff --git a/event_smart/src/main/java/com/njcn/product/event/report/pojo/dto/EventTemplate.java b/event_smart/src/main/java/com/njcn/product/event/report/pojo/dto/EventTemplate.java new file mode 100644 index 0000000..7347a52 --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/report/pojo/dto/EventTemplate.java @@ -0,0 +1,26 @@ +package com.njcn.product.event.report.pojo.dto; + +import lombok.Data; + +/** + * Description: + * Date: 2025/09/29 上午 9:40【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +@Data +public class EventTemplate { + private Integer sno; + private String timeId; + private String orgName; + private String subName; + private String busName; + private String scale; + private String duration; + + private String residualVoltage; + + private String userName; + +} diff --git a/event_smart/src/main/java/com/njcn/product/event/report/service/impl/EasyPoiWordExportServiceImpl.java b/event_smart/src/main/java/com/njcn/product/event/report/service/impl/EasyPoiWordExportServiceImpl.java index b9dc8ff..ad9f2c4 100644 --- a/event_smart/src/main/java/com/njcn/product/event/report/service/impl/EasyPoiWordExportServiceImpl.java +++ b/event_smart/src/main/java/com/njcn/product/event/report/service/impl/EasyPoiWordExportServiceImpl.java @@ -14,6 +14,7 @@ import com.njcn.product.event.devcie.mapper.PqLineMapper; import com.njcn.product.event.devcie.pojo.dto.LedgerBaseInfoDTO; import com.njcn.product.event.devcie.pojo.dto.PqsDeptDTO; import com.njcn.product.event.report.pojo.dto.BjCustomReportDTO; +import com.njcn.product.event.report.pojo.dto.EventTemplate; import com.njcn.product.event.report.pojo.param.ReportExportParam; import com.njcn.product.event.report.service.EasyPoiWordExportService; import com.njcn.product.event.report.utils.WordTemplate; @@ -25,15 +26,19 @@ import com.njcn.product.event.transientes.service.CommGeneralService; import com.njcn.product.event.transientes.service.MsgEventConfigService; import lombok.RequiredArgsConstructor; import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFTable; +import org.apache.poi.xwpf.usermodel.XWPFTableCell; +import org.apache.poi.xwpf.usermodel.XWPFTableRow; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import javax.servlet.http.HttpServletResponse; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.DoubleStream; +import java.util.stream.Stream; /** * @Author: cdf @@ -60,9 +65,13 @@ public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService { private final PqUserLineAssMapper pqUserLineAssMapper; private final PqUserLedgerMapper pqUserLedgerMapper; private final PqsDicTreeMapper pqsDicTreeMapper; + private final ObjectMapper mapper = new ObjectMapper(); + @Value("${business.wordTemplatePath}") + private String wordTemplatePath; - + @Override public void test(HttpServletResponse response, ReportExportParam param) { + try { List deptIds = commGeneralService.getLineIdsByRedis(param.getDeptId()); if (CollUtil.isEmpty(deptIds)) { @@ -100,8 +109,32 @@ public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService { } List pqsEventdetailList = pqsEventdetailMapper.selectList(lambdaQueryWrapper); + List> eventTemplateList = new ArrayList<>(); + for (int i = 0; i < pqsEventdetailList.size(); i++) { + PqsEventdetail pqsEventdetail = pqsEventdetailList.get(i); + EventTemplate eventTemplate = new EventTemplate(); + eventTemplate.setSno(i+1); + eventTemplate.setTimeId(pqsEventdetail.getTimeid().format(DatePattern.NORM_DATETIME_FORMATTER)+"."+pqsEventdetail.getMs()); + List baseLineInfo = pqLineMapper.getBaseLineInfo(Stream.of(pqsEventdetailList.get(i).getLineid()).collect(Collectors.toList())); + eventTemplate.setOrgName(baseLineInfo.get(0).getGdName()); + eventTemplate.setSubName(baseLineInfo.get(0).getStationName()); + eventTemplate.setBusName(baseLineInfo.get(0).getBusBarName()); + eventTemplate.setScale(pqsDicDataMap.get(baseLineInfo.get(0).getScale()).getDicName()); + eventTemplate.setDuration(String.format("%.3f",pqsEventdetail.getPersisttime()/1000)); + eventTemplate.setResidualVoltage(String.format("%.2f",pqsEventdetail.getEventvalue()*100)); + eventTemplate.setUserName(baseLineInfo.get(0).getObjName()); + Map eventMap = mapper.convertValue(eventTemplate,Map.class); + + eventTemplateList.add(eventMap); + } + bjReportDTO.setEvent(eventTemplateList); + bjReportDTO.setBjTotalEvent(pqsEventdetailList.size()); List lineIds = pqsEventdetailList.stream().map(PqsEventdetail::getLineid).distinct().collect(Collectors.toList()); + if(CollectionUtils.isEmpty(lineIds)){ + //如果lineIds为空添加一个不是监测点的监测点id避免后边查询错误 + lineIds.add(99999999); + } List ledgerBaseInfoDTOList = pqLineMapper.getBaseLedger(lineIds,null); long stationCount = ledgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getStationId).distinct().count(); bjReportDTO.setTotalEventSubstation((int)stationCount); @@ -109,9 +142,9 @@ public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService { bjReportDTO.setBjTotalBus((int)busCount); String busVoltageStr = busVoltageDeal(ledgerBaseInfoDTOList,pqsDicDataMap); bjReportDTO.setStationVoltage(busVoltageStr); - - double min = pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).min().getAsDouble()*100; - double max = pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).max().getAsDouble()*100; + //double容易精度缺失 + double min =Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).min().getAsDouble()*100*100)*0.01d ; + double max = Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).max().getAsDouble()*100*100)*0.01d; bjReportDTO.setResidualVoltageRange(min+"%-"+max+"%"); double minPersisTime = pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getPersisttime).min().getAsDouble()/1000; @@ -127,16 +160,163 @@ public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService { bjReportDTO.setObjTypeList(treeStr); bjReportDTO.setAffectedUserCount(pqUserLedgerPOList.size()); + areaAssemble(bjReportDTO,param,pqsDicDataMap); - ObjectMapper mapper = new ObjectMapper(); Map map = mapper.convertValue(bjReportDTO,Map.class); - WordTemplate.generateWordDownload("template/test.docx", response, "aa.docx", map); + WordTemplate.generateWordDownload(wordTemplatePath+"/test.docx", response, bjReportDTO.getDateFormat()+"重要敏感用户电压暂降事件监测情况.docx", map); } catch (Exception e) { e.printStackTrace(); } } + private void areaAssemble(BjCustomReportDTO bjReportDTO, ReportExportParam param, Map pqsDicDataMap) { + List pqsDeptsList = pqsDeptsMapper.getDeptList(param.getDeptList()); + Map deptMap = pqsDeptsList.stream().collect(Collectors.toMap(PqsDeptDTO::getDeptsIndex,PqsDeptDTO::getDeptsname)); + List areaContentList = new ArrayList<>(); + List> eventTemplateList = new ArrayList<>(); + + param.getDeptList().forEach(deptId->{ + String deptName = deptMap.get(deptId); + + String areaContent =""; + String userContext =""; + List deptLineIds = commGeneralService.getLineIdsByRedis(deptId); + if(CollectionUtils.isEmpty(deptLineIds)){ + areaContent = deptName+"共监测到电压暂降事件0条"; + }else { + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.in(PqsEventdetail::getWavetype,msgEventConfigService.getEventType()) + .gt(PqsEventdetail::getPersisttime,msgEventConfigService.getEventDuration()) + .le(PqsEventdetail::getEventvalue,msgEventConfigService.getEventValue()) + .between(PqsEventdetail::getTimeid,DateUtil.parse(param.getSearchBeginTime(),DatePattern.NORM_DATETIME_PATTERN),DateUtil.parse(param.getSearchEndTime(),DatePattern.NORM_DATETIME_PATTERN)); + if (deptLineIds.size() > 1000) { + List> listList = CollUtil.split(deptLineIds, 1000); + lambdaQueryWrapper.and(w->{ + w.or(i->{ + for(List ids : listList){ + i.in(PqsEventdetail::getLineid,ids); + } + }); + }); + } else { + lambdaQueryWrapper.in(PqsEventdetail::getLineid,deptLineIds); + } + List pqsEventdetailList = pqsEventdetailMapper.selectList(lambdaQueryWrapper); + if(CollectionUtils.isEmpty(pqsEventdetailList)){ + areaContent = deptName+"共监测到电压暂降事件0条"; + }else { + Integer eveCount = pqsEventdetailList.size(); + + List lineIds = pqsEventdetailList.stream().map(PqsEventdetail::getLineid).distinct().collect(Collectors.toList()); + List ledgerBaseInfoDTOList = pqLineMapper.getBaseLedger(lineIds,null); + long stationCount = ledgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getStationId).distinct().count(); + long busCount = ledgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getBusBarId).distinct().count(); + + String stationStr = stationVoltageDeal(ledgerBaseInfoDTOList,pqsDicDataMap); + String areabusVoltageDeal = areabusVoltageDeal(ledgerBaseInfoDTOList,pqsDicDataMap); + + double min =Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).min().getAsDouble()*100*100)*0.01d ; + double max = Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).max().getAsDouble()*100*100)*0.01d; + String residualVoltage = min+"%-"+max+"%"; + + double minPersisTime = pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getPersisttime).min().getAsDouble()/1000; + double maxPersisTime = pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getPersisttime).max().getAsDouble()/1000; + String duration = minPersisTime+"s-"+maxPersisTime+"s"; + String temp ="%s共监测到电压暂降事件%s条,涉及%s座变电站,%s条母线,其中:%s,造成%s发生电压暂降,残余电压范围为%s,持续时间范围为%s。"; + areaContent =String.format(temp,deptName,eveCount,stationCount,busCount,stationStr,areabusVoltageDeal,residualVoltage,duration); + + if(!CollectionUtils.isEmpty(lineIds)){ + List pqUserLineAssPOS = pqUserLineAssMapper.selectList(new LambdaQueryWrapper().in(PqUserLineAssPO::getLineIndex,lineIds)); + List userIds = pqUserLineAssPOS.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList()); + + LambdaQueryWrapper pqUserLedgerPOLambdaQueryWrapper = new LambdaQueryWrapper(); + pqUserLedgerPOLambdaQueryWrapper.in(PqUserLedgerPO::getId,userIds).eq(PqUserLedgerPO::getIsShow,1); + List pqUserLedgerPOList = pqUserLedgerMapper.selectList(pqUserLedgerPOLambdaQueryWrapper); + if(CollectionUtils.isEmpty(pqUserLedgerPOList)){ + userContext ="不涉及半导体及重点关注用户。"; + }else { + String companyName = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.joining("、", "(", ")")); + userContext="涉及"+pqUserLedgerPOList.size()+"家半导体及重点关注用户"+companyName+","; + //逆推监测点,过滤发生暂降事件 + List companyId = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getId).collect(Collectors.toList()); + List pqUserLineAssPOS1 = pqUserLineAssMapper.selectList(new LambdaQueryWrapper().in(PqUserLineAssPO::getUserIndex, companyId)); + List companyNameList = pqUserLedgerPOList.stream().map(PqUserLedgerPO::getCustomerName).collect(Collectors.toList()); + List companyLineId= pqUserLineAssPOS1.stream().map(PqUserLineAssPO::getLineIndex).collect(Collectors.toList()); + List companyevent = pqsEventdetailList.stream().filter(pqsEventdetail -> companyLineId.contains(pqsEventdetail.getLineid())).collect(Collectors.toList()); + if(CollectionUtils.isEmpty(companyevent)){ + userContext =userContext+"暂未发生暂态事件。"; + }else { + + for (int i = 0; i < pqsEventdetailList.size(); i++) { + PqsEventdetail pqsEventdetail = pqsEventdetailList.get(i); + + List baseLineInfo = pqLineMapper.getBaseLineInfo(Stream.of(pqsEventdetailList.get(i).getLineid()).collect(Collectors.toList())); + String[] split = baseLineInfo.get(0).getObjName().split(";"); + for (int i1 = 0; i1 < split.length; i1++) { + if(companyNameList.contains(split[i1])){ + EventTemplate eventTemplate = new EventTemplate(); + eventTemplate.setTimeId(pqsEventdetail.getTimeid().format(DatePattern.NORM_DATETIME_FORMATTER)+"."+pqsEventdetail.getMs()); + eventTemplate.setOrgName(baseLineInfo.get(0).getGdName()); + eventTemplate.setSubName(baseLineInfo.get(0).getStationName()); + eventTemplate.setBusName(baseLineInfo.get(0).getBusBarName()); + eventTemplate.setScale(pqsDicDataMap.get(baseLineInfo.get(0).getScale()).getDicName()); + eventTemplate.setDuration(String.format("%.3f",pqsEventdetail.getPersisttime()/1000)); + eventTemplate.setResidualVoltage(String.format("%.2f",pqsEventdetail.getEventvalue()*100)); + eventTemplate.setUserName(split[i1]); + Map eventMap = mapper.convertValue(eventTemplate,Map.class); + eventTemplateList.add(eventMap); + } + + } + + + + } + Integer companyEveCount = companyevent.size(); + + List companyLineIds = companyevent.stream().map(PqsEventdetail::getLineid).distinct().collect(Collectors.toList()); + List companyLedgerBaseInfoDTOList = pqLineMapper.getBaseLedger(companyLineIds,null); + long companyStationCount = companyLedgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getStationId).distinct().count(); + long companyBusCount = companyLedgerBaseInfoDTOList.stream().map(LedgerBaseInfoDTO::getBusBarId).distinct().count(); + + String companyStationStr = stationVoltageDeal(companyLedgerBaseInfoDTOList,pqsDicDataMap); + String companyAreabusVoltageDeal = areabusVoltageDeal(companyLedgerBaseInfoDTOList,pqsDicDataMap); + + double companyMin =Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).min().getAsDouble()*100*100)*0.01d ; + double companyMax = Math.round(pqsEventdetailList.stream().mapToDouble(PqsEventdetail::getEventvalue).max().getAsDouble()*100*100)*0.01d; + String companyResidualVoltage = companyMin+"%-"+companyMax+"%"; + + double companyMinPersisTime = companyevent.stream().mapToDouble(PqsEventdetail::getPersisttime).min().getAsDouble()/1000; + double companyMaxPersisTime = companyevent.stream().mapToDouble(PqsEventdetail::getPersisttime).max().getAsDouble()/1000; + String companyDuration = companyMinPersisTime+"s-"+companyMaxPersisTime+"s"; + String companyTemp =" 电压暂降事件%s条,变电站%s座,母线%s条,其中:%s,造成%s发生电压暂降,残余电压范围为%s,持续时间范围为%s。"; + userContext = userContext+String.format(companyTemp,companyEveCount,companyStationCount,companyBusCount,companyStationStr,companyAreabusVoltageDeal,companyResidualVoltage,companyDuration); + } + + } + }else { + userContext ="不涉及半导体及重点关注用户。"; + } + + + } + + } + + areaContent =areaContent+userContext; + + areaContentList.add(areaContent); + }); + // 或者直接使用 \n + String result2 = String.join("\n", areaContentList); + bjReportDTO.setAreaContent(result2); + eventTemplateList.sort(Comparator.comparing(map -> (String) map.get("userName"))); + + bjReportDTO.setCompanyEvent(eventTemplateList); + + } + private void addUserDataToTable(XWPFDocument document) { // 创建表格 // 填充数据到表格(此处为示例代码框架,实际需完善表格创建和数据填充逻辑) @@ -193,7 +373,7 @@ public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService { List dtoList = pqLineMapper.getBaseLedger(temIds, null); long innerStation = dtoList.stream().map(LedgerBaseInfoDTO::getStationId).distinct().count(); - long innerBus = dtoList.stream().map(LedgerBaseInfoDTO::getStationId).distinct().count(); + long innerBus = dtoList.stream().map(LedgerBaseInfoDTO::getBusBarId).distinct().count(); strBuilderInner.append(String.valueOf(innerStation)).append("座,母线").append(String.valueOf(innerBus)).append("条,其中:"); Map> scaleInnerMap = dtoList.stream().collect(Collectors.groupingBy(LedgerBaseInfoDTO::getScale)); @@ -210,10 +390,15 @@ public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService { .collect(Collectors.joining(StrUtil.COMMA)); strBuilderInner.append(resultContent).append(";"); temStr.append(strBuilderInner); - } - bjReportDTO.setAreaInfo(temStr.toString()); - bjReportDTO.setDateFormat(DateUtil.format(DateUtil.parse(param.getSearchBeginTime()), DatePattern.NORM_DATE_PATTERN)); + } + bjReportDTO.setAreaInfo(temStr.toString().substring(0,temStr.length()-1)); + if(DateUtil.format(DateUtil.parse(param.getSearchBeginTime()), DatePattern.CHINESE_DATE_FORMATTER).equals(DateUtil.format(DateUtil.parse(param.getSearchEndTime()), DatePattern.CHINESE_DATE_FORMATTER))){ + bjReportDTO.setDateFormat(DateUtil.format(DateUtil.parse(param.getSearchBeginTime()), DatePattern.CHINESE_DATE_FORMATTER)); + }else { + bjReportDTO.setDateFormat(DateUtil.format(DateUtil.parse(param.getSearchBeginTime()), DatePattern.CHINESE_DATE_FORMATTER)+"-"+DateUtil.format(DateUtil.parse(param.getSearchEndTime()), DatePattern.CHINESE_DATE_FORMATTER)); + + } bjReportDTO.setTotalDevice((int) devCount); bjReportDTO.setTotalSubstation((int) stationCount); bjReportDTO.setTotalBus((int) busCount); @@ -236,6 +421,37 @@ public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService { return result; } + private String areabusVoltageDeal(List ledgerList,Map pqsDicDataMap){ + Map> scaleMap = ledgerList.stream().collect(Collectors.groupingBy(LedgerBaseInfoDTO::getScale)); + String result = scaleMap.entrySet().stream() + .map(entry -> { + String scale = entry.getKey(); + long busNum = entry.getValue().stream() + .map(LedgerBaseInfoDTO::getBusBarId) + .distinct() + .count(); + return busNum + "条"+pqsDicDataMap.get(scale).getDicName() + "母线" ; + }) + // 用分号连接 + .collect(Collectors.joining(StrUtil.COMMA)); + return result; + } + private String stationVoltageDeal(List ledgerList,Map pqsDicDataMap){ + Map> scaleMap = ledgerList.stream().collect(Collectors.groupingBy(LedgerBaseInfoDTO::getScale)); + String result = scaleMap.entrySet().stream() + .map(entry -> { + String scale = entry.getKey(); + long stationNum = entry.getValue().stream() + .map(LedgerBaseInfoDTO::getStationId) + .distinct() + .count(); + return pqsDicDataMap.get(scale).getDicName() + "变电站" + stationNum + "座"; + }) + // 用分号连接 + .collect(Collectors.joining(StrUtil.COMMA)); + return result; + } + private String userToStr(Map> stringListMap,Map treePOMap){ String result = stringListMap.entrySet().stream() .map(entry -> { @@ -250,4 +466,13 @@ public class EasyPoiWordExportServiceImpl implements EasyPoiWordExportService { .collect(Collectors.joining(StrUtil.COMMA)); return result; } + + + + public static void main(String[] args) { + String temp ="共监测到电压暂降事件%s条,涉及%s座变电站"; + String format = String.format(temp, 111, 111); + System.out.println(format); + + } } diff --git a/event_smart/src/main/java/com/njcn/product/event/report/utils/WordTemplate.java b/event_smart/src/main/java/com/njcn/product/event/report/utils/WordTemplate.java index 0df4936..cd35cf8 100644 --- a/event_smart/src/main/java/com/njcn/product/event/report/utils/WordTemplate.java +++ b/event_smart/src/main/java/com/njcn/product/event/report/utils/WordTemplate.java @@ -2,6 +2,10 @@ package com.njcn.product.event.report.utils; import cn.afterturn.easypoi.word.WordExportUtil; import org.apache.poi.xwpf.usermodel.XWPFDocument; +import org.apache.poi.xwpf.usermodel.XWPFTable; +import org.apache.poi.xwpf.usermodel.XWPFTableCell; +import org.apache.poi.xwpf.usermodel.XWPFTableRow; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge; import java.io.*; import java.net.URL; @@ -55,12 +59,13 @@ public class WordTemplate { response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("UTF-8"), "ISO8859-1")); response.setCharacterEncoding("UTF-8"); // 1. 处理模板路径并获取输入流 - String temPath = getTemplateInputStream(templatePath); - if (temPath == null) { - throw new FileNotFoundException("模板文件不存在: " + templatePath); - } +// String temPath = getTemplateInputStream(templatePath); +// if (temPath == null) { +// throw new FileNotFoundException("模板文件不存在: " + templatePath); +// } // 渲染文档并响应 - XWPFDocument document = WordExportUtil.exportWord07(temPath, data); + XWPFDocument document = WordExportUtil.exportWord07(templatePath, data); + mergeTableCells(document); try (OutputStream outputStream = response.getOutputStream()) { document.write(outputStream); } catch (Exception e) { @@ -94,7 +99,86 @@ public class WordTemplate { } } + /** + * 手动合并表格单元格 + * 合并规则:相邻行中指定列的值相同时进行合并 + */ + private static void mergeTableCells(XWPFDocument doc) { + // 获取文档中的所有表格 + List tables = doc.getTables(); + for (XWPFTable table : tables) { + int rowCount = table.getNumberOfRows(); + if (rowCount <= 1) continue; + + // 定义需要合并的列索引(根据你的表格结构调整) + int[] mergeColumns = {0}; // 第1列(姓名)和第2列(班级)需要合并 + + for (int colIndex : mergeColumns) { + mergeVerticalCells(table, colIndex); + } + } + } + + /** + * 垂直合并指定列的相同值单元格 + */ + private static void mergeVerticalCells(XWPFTable table, int colIndex) { + int rowCount = table.getNumberOfRows(); + int mergeStartRow = -1; + String previousValue = null; + + for (int i = 0; i < rowCount; i++) { + XWPFTableRow row = table.getRow(i); + if (row == null) continue; + + XWPFTableCell cell = row.getCell(colIndex); + if (cell == null) continue; + + String currentValue = cell.getText(); + + if (currentValue.equals(previousValue)) { + // 值相同,继续合并区间 + if (mergeStartRow == -1) { + mergeStartRow = i - 1; + } + // 如果是最后一行,需要执行合并 + if (i == rowCount - 1) { + mergeCells(table, colIndex, mergeStartRow, i); + } + } else { + // 值不同,合并之前的区间 + if (mergeStartRow != -1) { + mergeCells(table, colIndex, mergeStartRow, i - 1); + mergeStartRow = -1; + } + previousValue = currentValue; + } + } + } + + /** + * 执行单元格合并 + */ + private static void mergeCells(XWPFTable table, int colIndex, int startRow, int endRow) { + if (startRow >= endRow) return; + + for (int i = startRow; i <= endRow; i++) { + XWPFTableRow row = table.getRow(i); + if (row != null) { + XWPFTableCell cell = row.getCell(colIndex); + if (cell != null) { + if (i == startRow) { + // 起始行设置合并属性 + cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART); + } else { + // 后续行设置为继续合并 + cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE); + } + } + } + } + } /** * 获取模板文件输入流(优先从classpath查找,再查找绝对路径) * diff --git a/event_smart/src/main/resources/application.yml b/event_smart/src/main/resources/application.yml index aebfa05..ffa4f8d 100644 --- a/event_smart/src/main/resources/application.yml +++ b/event_smart/src/main/resources/application.yml @@ -38,6 +38,7 @@ db: business: #处理波形数据位置 wavePath: D://Comtrade + wordTemplatePath: D:/wordTemplatePath #wavePath: /usr/local/comtrade #处理临时数据 tempPath: D://file @@ -70,3 +71,4 @@ threadPool: WAVEPATH: D:/Comtrade + diff --git a/event_smart/src/main/resources/template/test.docx b/event_smart/src/main/resources/template/test.docx index 3c7d4ae..5ca61eb 100644 Binary files a/event_smart/src/main/resources/template/test.docx and b/event_smart/src/main/resources/template/test.docx differ