package com.whyc.service; import com.whyc.pojo.db_batt.PowerInf; import com.whyc.pojo.db_dis_batt.BattTestInf; import com.whyc.pojo.db_power_history.BattRealTimeDataHistory; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.xssf.usermodel.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.FileOutputStream; import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.stream.Collectors; @Service public class ExcelService { @Autowired private PowerInfService powerInfService; @Autowired private BattTestInfService battTestInfService; @Autowired //private static BattRealTimeDataHistoryService battRTDataHisService; private BattRealTimeDataHistoryService battRTDataHisService; /** * 将电池组放电充电数据写入excel * 传入参数: * 电池组id,放电第几次 * * @throws IOException */ public void dcReport(int battGroupId,int testRecordCount) throws IOException { String filePath = "C:\\Users\\29550\\Desktop\\当前项目\\2023\\0乌东德系统\\测试.xlsx"; //创建一个工作簿 XSSFWorkbook workbook = new XSSFWorkbook(); //创建sheet1 createSheet1(workbook,battGroupId,testRecordCount); // 将工作簿写入文件 FileOutputStream fileOut = new FileOutputStream(filePath); workbook.write(fileOut); // 关闭工作簿 workbook.close(); } public static void main(String[] args) throws IOException { //dcReport(1,1); } //private static void createSheet1(XSSFWorkbook workbook, int battGroupId, int testRecordCount) { private void createSheet1(XSSFWorkbook workbook, int battGroupId, int testRecordCount) { XSSFSheet sheet = workbook.createSheet("放电充电电压数据报表"); //总的列数根据 放电时长和充电时长决定 //数据准备 PowerInf battInfo = powerInfService.getByBattGroupId(battGroupId); //TODO 测试数据 //PowerInf battInfo = new PowerInf(); //battInfo.setPowerName("测试直流系统"); //battInfo.setBattGroupName("蓄电池组1"); BattTestInf battTestInf = battTestInfService.getDischargeRecord(battGroupId,testRecordCount); //TODO 测试数据 //BattTestInf battTestInf = new BattTestInf(); //battTestInf.setTestTimelong(36000); //battTestInf.setTestStarttime(new Date()); //单位是秒,转化为分钟 Integer testTimeLong = battTestInf.getTestTimelong(); Integer testTimeMinutes = testTimeLong /60; //testTimeLong转为小时.保留1位小数,取小进行切割 Float testTimeHours = BigDecimal.valueOf(testTimeLong).divide(BigDecimal.valueOf(60 * 60), 1, RoundingMode.FLOOR).floatValue(); //获取放电开始时间和终止时间 Date dischargeStartTime = battTestInf.getTestStarttime(); //终止时间为开始时间加 测试时长 Calendar dischargeEndTime = Calendar.getInstance(); dischargeEndTime.setTime(dischargeStartTime); dischargeEndTime.add(Calendar.SECOND, testTimeLong); //放电结束后的充电终止记录 //BattRealTimeDataHistory hisChargeEnd = battRTDataHisService.getChargeEnd(battGroupId,dischargeEndTime); //TODO 测试数据 //BattRealTimeDataHistory hisChargeEnd = new BattRealTimeDataHistory(); //Calendar chargeEndTime = Calendar.getInstance(); //chargeEndTime.setTime(new Date()); //chargeEndTime.add(Calendar.HOUR,15); //hisChargeEnd.setRecordTime(chargeEndTime.getTime()); //充电时长=充电终止时间-放电终止时间 long chargeTimeSeconds = (dischargeEndTime.getTime().getTime() - dischargeStartTime.getTime()) / 1000; //long chargeTimeSeconds = (hisChargeEnd.getRecordTime().getTime() - dischargeStartTime.getTime()) / 1000; //chargeTimeSeconds转为小时.保留1位小数,取小进行切割 Float chargeTimeHours = BigDecimal.valueOf(chargeTimeSeconds).divide(BigDecimal.valueOf(60 * 60), 1, RoundingMode.FLOOR).floatValue(); //行数是固定的.总列数是根据放电时长和充电时长决定的 //放电时长导致的列数计算,列为0.5h,1h,2h,3h,...; //小于0.5h,没列. 0.5h~1h之间,1列-0.5h. 大于1h,1+ 放电时长的列数. int dischargeColumnCount; if (testTimeHours < 0.5) { dischargeColumnCount = 0; } else if (testTimeHours >= 0.5 && testTimeHours < 1) { //0.5h 占两列 dischargeColumnCount = 2; } else if (testTimeHours >= 1 && testTimeHours < 2) { //0.5h 占两列,1h 占两列 dischargeColumnCount = 4; } else { dischargeColumnCount = (int) (testTimeHours + 3); } //充电时长导致的列数计算,列为0.5h,1h,2h,3h,...; int chargeColumnCount; if (chargeTimeHours < 0.5) { chargeColumnCount = 0; } else if (chargeTimeHours >= 0.5 && chargeTimeHours < 1) { chargeColumnCount = 1; } else { chargeColumnCount = (int) (chargeTimeHours + 1); } //列数的计算= 蓄电池号(1行)+浮充电压值(2行)+放电前开路电压(2行)+放电特定时间电压(dischargeColumnCount行)+放电结束0.5h开路电压值(1行)+充电特定时间电压(chargeColumnCount行)+满电开路电压值(1行)+备注(1行) int columnCount = 1 + 2 + 2 + dischargeColumnCount + 1 + chargeColumnCount + 1 + 1; //字体加粗样式 XSSFCellStyle cellStyleFontBold = workbook.createCellStyle(); Font font = workbook.createFont(); font.setBold(true); cellStyleFontBold.setFont(font); //创建第一行是标题行 XSSFCell cellRow1 = sheet.createRow(0).createCell(0); setRowStyle(sheet.getRow(0),cellStyleFontBold); cellRow1.setCellValue(battInfo.getPowerName()+battInfo.getBattGroupName()+"核对性放电、充电试验记录表"); //合并行列,占据的列是columnCount列合并为1列并居中 CellRangeAddress region = new CellRangeAddress(0, 0, 0, columnCount-1); sheet.addMergedRegion(region); //TODO 第二行的合并列是根据变动的,后续调整 CellRangeAddress region21 = new CellRangeAddress(1, 1, 0, 1); sheet.addMergedRegion(region21); CellRangeAddress region22 = new CellRangeAddress(1, 1, 3, 9); sheet.addMergedRegion(region22); CellRangeAddress region23 = new CellRangeAddress(1, 1, 10, 13); sheet.addMergedRegion(region23); CellRangeAddress region24 = new CellRangeAddress(1, 1, 14, 17); sheet.addMergedRegion(region24); CellRangeAddress region25 = new CellRangeAddress(1, 1, 18, 24); sheet.addMergedRegion(region25); //第三行的合并列 CellRangeAddress region31 = new CellRangeAddress(2, 2, 1, 2); CellRangeAddress region32 = new CellRangeAddress(2, 2, 3, 4); CellRangeAddress region33 = new CellRangeAddress(2, 2, 5, 6); CellRangeAddress region34 = new CellRangeAddress(2, 2, 7, 8); sheet.addMergedRegion(region31); sheet.addMergedRegion(region32); sheet.addMergedRegion(region33); sheet.addMergedRegion(region34); // 创建居中样式 CellStyle style = workbook.createCellStyle(); style.setAlignment(HorizontalAlignment.CENTER); style.setVerticalAlignment(VerticalAlignment.CENTER); // 应用样式到单元格 cellRow1.setCellStyle(style); //第二行是放电基本信息 XSSFRow row1 = sheet.createRow(1); XSSFCell cell1Row2 = row1.createCell(0); cell1Row2.setCellValue("蓄电池组号:" + battInfo.getBattGroupName()); XSSFCell cell2Row2 = row1.createCell(2); cell2Row2.setCellValue(""); XSSFCell cell3Row2 = row1.createCell(3); cell3Row2.setCellValue("工作票号:2273925\n" + "工作负责人:马云燕\n" + "工作成员:周素文、李志标、王月灿等"); XSSFCell cell4Row2 = row1.createCell(10); cell4Row2.setCellValue("放电日期:2021.10.30\n" + "放电开始时间:10:00\n" + "放电结束时间:19:47"); XSSFCell cell5Row2 = row1.createCell(14); cell5Row2.setCellValue("放电电流(A):35\n" + "放电时长(时.分):600min\n" + "放电容量(Ah):300"); XSSFCell cell6Row2 = row1.createCell(18); cell6Row2.setCellValue("环境温度(℃):24.5\n" + "环境湿度(%):46.7"); //第二行设置加粗 setRowStyle(sheet.getRow(1),cellStyleFontBold); //第三行是电池号和电压等相关抬头 XSSFRow row2 = sheet.createRow(2); row2.createCell(0).setCellValue("蓄电池号(#)"); row2.createCell(1).setCellValue("蓄电池浮充电压值(V)"); row2.createCell(3).setCellValue("放电前蓄电池开路电压值(V)"); //放电特定电压值 int columnIndex = 3; if(dischargeColumnCount > 0){ row2.createCell(5).setCellValue("放电0.5h蓄电池电压值(V)"); columnIndex+=2; if(dischargeColumnCount > 2){ //合并单元格了,所以索引+2 row2.createCell(7).setCellValue("放电1h蓄电池电压值(V)"); columnIndex+=2; if(dischargeColumnCount > 4){ columnIndex++; //放电nh蓄电池电压值(V),n从2开始 for(int i = 4;i < dischargeColumnCount;i++){ row2.createCell(i+5).setCellValue("放电" + (i-2) + "h蓄电池电压值(V)"); columnIndex++; } } } } //充电特定电压值 row2.createCell(++columnIndex).setCellValue("放电结束0.5h后蓄电池开路电压值(V)"); if(chargeColumnCount > 0){ columnIndex++; row2.createCell(columnIndex).setCellValue("充电0.5h"); if(chargeColumnCount > 1){ //充电nh,n从1开始 for(int i = 1;i < chargeColumnCount;i++){ columnIndex++; row2.createCell(columnIndex).setCellValue("充电" + (i) + "h蓄电池电压值(V)"); } } } row2.createCell(++columnIndex).setCellValue("充满后蓄电池电压值(V)(电流为0)"); row2.createCell(++columnIndex).setCellValue("备注"); //从rowIndex=6开始 int rowIndex = 6; // 共104节单体,104行. 进行遍历,填充 //蓄电池浮充电压值列表 List fcVolList = new ArrayList<>(); fcVolList = battRTDataHisService.getFcVolList(battGroupId,dischargeStartTime); //按单体编号排序,按编号升序 fcVolList.sort(Comparator.comparingInt(BattRealTimeDataHistory::getMonNum)); //放点前蓄电池开路电压值 List preVolList = new ArrayList<>(); preVolList = battRTDataHisService.getPreVolList(battGroupId,dischargeStartTime); addStatistics(fcVolList); addStatistics(preVolList); //一共104节单体,再加上统计数据4列,一共108 for(int j = 0; j < 108; j++){ XSSFRow rowTemp = sheet.createRow(rowIndex++); if(j<104) { rowTemp.createCell(0).setCellValue((j + 1) + "#"); }else{ if(j == 104){ rowTemp.createCell(0).setCellValue("单节平均电压"); }else if (j == 105){ rowTemp.createCell(0).setCellValue("单节最大电压"); }else if (j == 106){ rowTemp.createCell(0).setCellValue("单节最小电压"); }else{ rowTemp.createCell(0).setCellValue("单节最大差值"); } } //rowTemp.createCell(1).setCellValue("蓄电池浮充电压值(V):"+(j+1)+"#"); //rowTemp.createCell(2).setCellValue("蓄电池浮充温度值:"+(j+1)+"#"); //rowTemp.createCell(3).setCellValue("放电前蓄电池开路电压值(V):"+(j+1)+"#"); //rowTemp.createCell(4).setCellValue("放电前蓄电池开路温度值:"+(j+1)+"#"); rowTemp.createCell(1).setCellValue(fcVolList.get(j).getMonVol()); rowTemp.createCell(1).setCellValue(fcVolList.get(j).getMonTmp()); rowTemp.createCell(1).setCellValue(preVolList.get(j).getMonVol()); rowTemp.createCell(1).setCellValue(preVolList.get(j).getMonTmp()); //放电特定电压值 int columnIndexTemp = 3; Calendar dischargeCalendar = Calendar.getInstance(); dischargeCalendar.setTime(dischargeStartTime); if(dischargeColumnCount > 0){ //时间在测试开始时间+0.5h dischargeCalendar.add(Calendar.MINUTE,30); Date recordTime = dischargeCalendar.getTime(); List dischargeListOne = battRTDataHisService.getRecordList(battGroupId,recordTime); //按单体编号排序,按编号升序 dischargeListOne.sort(Comparator.comparingInt(BattRealTimeDataHistory::getMonNum)); addStatistics(dischargeListOne); //rowTemp.createCell(5).setCellValue("放电0.5h电压值(V):"+(j+1)+"#"); //rowTemp.createCell(6).setCellValue("放电0.5h温度值:"+(j+1)+"#"); rowTemp.createCell(5).setCellValue(dischargeListOne.get(j).getMonVol()); rowTemp.createCell(6).setCellValue(dischargeListOne.get(j).getMonTmp()); columnIndexTemp+=2; if(dischargeColumnCount > 2){ //合并单元格了,所以索引+2 //时间在测试开始时间+1h dischargeCalendar.setTime(dischargeStartTime); dischargeCalendar.add(Calendar.HOUR,1); Date recordTimeTwo = dischargeCalendar.getTime(); List dischargeListTwo = battRTDataHisService.getRecordList(battGroupId,recordTimeTwo); dischargeListTwo.sort(Comparator.comparingInt(BattRealTimeDataHistory::getMonNum)); addStatistics(dischargeListTwo); //rowTemp.createCell(7).setCellValue("放电1h电压值(V):"+(j+1)+"#"); //rowTemp.createCell(8).setCellValue("放电1h温度值:"+(j+1)+"#"); rowTemp.createCell(7).setCellValue(dischargeListTwo.get(j).getMonVol()); rowTemp.createCell(8).setCellValue(dischargeListTwo.get(j).getMonTmp()); columnIndexTemp+=2; if(dischargeColumnCount > 4){ columnIndexTemp++; //放电nh蓄电池电压值(V),n从2开始 for(int i = 4;i < dischargeColumnCount;i++){ int dischargeHour = i-2; //时间在测试开始时间+nh dischargeCalendar.setTime(dischargeStartTime); dischargeCalendar.add(Calendar.HOUR,dischargeHour); Date recordTimeN = dischargeCalendar.getTime(); List dischargeListN = battRTDataHisService.getRecordList(battGroupId,recordTimeN); dischargeListN.sort(Comparator.comparingInt(BattRealTimeDataHistory::getMonNum)); addStatistics(dischargeListN); //rowTemp.createCell(i+5).setCellValue("放电" + dischargeHour + "h蓄电池电压值(V)"); rowTemp.createCell(i+5).setCellValue(dischargeListN.get(j).getMonVol()); columnIndexTemp++; } } } } //充电特定电压值 Calendar dischargeEndCalendar = Calendar.getInstance(); dischargeEndCalendar.setTime(dischargeEndTime.getTime()); dischargeEndCalendar.add(Calendar.MINUTE,30); List dischargeSetVolListOne = battRTDataHisService.getRecordList(battGroupId, dischargeEndCalendar.getTime()); dischargeSetVolListOne.sort(Comparator.comparingInt(BattRealTimeDataHistory::getMonNum)); addStatistics(dischargeSetVolListOne); rowTemp.createCell(++columnIndexTemp).setCellValue(dischargeSetVolListOne.get(j).getMonVol()); //定位到充电开始时间,状态变为充电的记录时间 Date chargeStartTime = battRTDataHisService.getChargeStartTime(battGroupId, dischargeEndTime.getTime()); if(chargeColumnCount > 0){ Calendar chargeCalendar = Calendar.getInstance(); chargeCalendar.setTime(chargeStartTime); chargeCalendar.add(Calendar.MINUTE,30); List chargeVolListOne = battRTDataHisService.getRecordList(battGroupId, chargeCalendar.getTime()); chargeVolListOne.sort(Comparator.comparingInt(BattRealTimeDataHistory::getMonNum)); addStatistics(chargeVolListOne); columnIndexTemp++; //rowTemp.createCell(columnIndexTemp).setCellValue("充电0.5h"); rowTemp.createCell(columnIndexTemp).setCellValue(chargeVolListOne.get(j).getMonVol()); if(chargeColumnCount > 1){ //充电nh,n从1开始 for(int i = 1;i < chargeColumnCount;i++){ columnIndexTemp++; chargeCalendar.setTime(chargeStartTime); chargeCalendar.add(Calendar.HOUR,i); List chargeVolListN = battRTDataHisService.getRecordList(battGroupId, chargeCalendar.getTime()); chargeVolListN.sort(Comparator.comparingInt(BattRealTimeDataHistory::getMonNum)); addStatistics(chargeVolListN); //rowTemp.createCell(columnIndexTemp).setCellValue("充电" + (i) + "h蓄电池电压值(V)"); rowTemp.createCell(columnIndexTemp).setCellValue(chargeVolListN.get(j).getMonVol()); } } } Calendar chargeCalendar = Calendar.getInstance(); chargeCalendar.setTime(chargeStartTime); List fcVolListAfter = battRTDataHisService.getFcVolListAfter(battGroupId, chargeCalendar.getTime()); fcVolListAfter.sort(Comparator.comparingInt(BattRealTimeDataHistory::getMonNum)); addStatistics(fcVolListAfter); //rowTemp.createCell(++columnIndexTemp).setCellValue("充满后蓄电池电压值(V)(电流为0)"); if (fcVolListAfter.size() > 0){ rowTemp.createCell(++columnIndexTemp).setCellValue(fcVolListAfter.get(j).getMonVol()); }else { rowTemp.createCell(++columnIndexTemp).setCellValue("-"); } rowTemp.createCell(++columnIndexTemp).setCellValue("-"); } //=====================格式设置=====================// //设置列宽 for (int i = 0; i < columnCount; i++) { sheet.setColumnWidth(i, 256 * 20); } //对整个表格进行全局设置,暂为设置边框 addGlobalStylesToAllCells(sheet, workbook); } //对传入的BattRealTimeDataHistory列表进行统计,将统计结果也追加到列表中 public void addStatistics(List battRealTimeDataHistoryList) { if(battRealTimeDataHistoryList != null && battRealTimeDataHistoryList.size() > 0){ //电压平均值,最大值,最小值,最大差值 List volList = battRealTimeDataHistoryList.stream().map(BattRealTimeDataHistory::getMonVol).collect(Collectors.toList()); Double volAvgDouble = volList.stream().collect(Collectors.averagingDouble(Float::floatValue)); BigDecimal avg = new BigDecimal(volAvgDouble).setScale(4, RoundingMode.HALF_UP); float volAvg = avg.floatValue(); //最大值 float volMax = volList.stream().max(Float::compareTo).get(); BigDecimal max = new BigDecimal(volMax).setScale(4, RoundingMode.HALF_UP); volMax = max.floatValue(); //最小值 float volMin = volList.stream().min(Float::compareTo).get(); BigDecimal min = new BigDecimal(volMin).setScale(4, RoundingMode.HALF_UP); volMin = min.floatValue(); //最大差值 float volGap = volMax - volMin; BattRealTimeDataHistory hisAvg = new BattRealTimeDataHistory(); hisAvg.setMonVol(volAvg); BattRealTimeDataHistory hisMax = new BattRealTimeDataHistory(); hisMax.setMonVol(volMax); BattRealTimeDataHistory hisMin = new BattRealTimeDataHistory(); hisMin.setMonVol(volMin); BattRealTimeDataHistory hisGap = new BattRealTimeDataHistory(); hisGap.setMonVol(volGap); battRealTimeDataHistoryList.add(hisAvg); battRealTimeDataHistoryList.add(hisMax); battRealTimeDataHistoryList.add(hisMin); battRealTimeDataHistoryList.add(hisGap); } } public void setRowStyle(Row row, CellStyle style) { for (Cell cell : row) { cell.setCellStyle(style); } } /** * 这个方法最后执行,用于对已被创建的行内的所有单元格添加边框.能自动识别被创建的所有列和所有单元格 * @param sheet * @param workbook */ public void addGlobalStylesToAllCells(Sheet sheet, Workbook workbook) { //所有边框样式 CellStyle borderedStyle = workbook.createCellStyle(); //borderedStyle.cloneStyleFrom(sheet.getRow(0).getCell(0).getCellStyle()); // 可选:复制已有样式 borderedStyle.setBorderTop(BorderStyle.THIN); borderedStyle.setBorderBottom(BorderStyle.THIN); borderedStyle.setBorderLeft(BorderStyle.THIN); borderedStyle.setBorderRight(BorderStyle.THIN); for (Row row : sheet) { for (Cell cell : row) { cell.setCellStyle(borderedStyle); } } } }