使用POI原生自界说输出定制化表格

[复制链接]
发表于 2025-11-23 17:52:41 | 显示全部楼层 |阅读模式
在工作中偶然候会遇到一些统计功能,须要输出的内容并不是很规则的第一行表头反面满是数据的格式,而是如许

这就导致没法用一些封装好的工具(比方easyExcel)简单快捷的输出,这时间只能使用poi举行原生的制作表格,在工作中我使用到了这部门功能,现在将代码贴在如下举行纪录
  1. public void downloadReport(HttpServletResponse response) {
  2.         // 创建工作簿
  3.         Workbook workbook = new XSSFWorkbook();
  4.         //概览
  5.         handeleOverView(workbook);
  6.         handeleMonthAvgDay(workbook);
  7.         handeleMonthLightUsageRation(workbook);
  8.         try {
  9.             response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  10.             response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("光伏运行报告.xlsx", "UTF-8"));
  11.             workbook.write(response.getOutputStream());
  12.             workbook.close();
  13.         } catch (
  14.                 IOException e) {
  15.             e.printStackTrace();
  16.         }
  17.     }
复制代码
  1.     private void handeleOverView(Workbook workbook) {
  2.         Sheet overview = workbook.createSheet("概览");
  3.         LocalDateTime now = LocalDateTime.now();
  4.         //昨天
  5.         LocalDateTime localDateTime = now.minusDays(1);
  6.         String nowStr = localDateTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
  7.         // 创建数据
  8.         //设置合并居中和自动换行
  9.         // 设置标题行,合并单元格并设置样式
  10.         Row row = overview.createRow(0);
  11.         overview.addMergedRegion(new CellRangeAddress(0, 0, 0, 5)); // 合并
  12.         Cell headerCell = row.createCell(0);
  13.         headerCell.setCellValue("光伏用电运行数据(统计2023年5月01日-" + nowStr + ")");
  14.         Row row2 = overview.createRow(1);
  15.         row2.createCell(0).setCellValue("总用电量(kwh)");
  16.         //查询昨日的最后一条数据和2023年5月1日的最后一条数据
  17.         PLightDevice firstData = lightDeviceDao.selectOne(new LambdaQueryWrapper<>(PLightDevice.class).eq(PLightDevice::getYear, 2023)
  18.                 .eq(PLightDevice::getMonth, 5).eq(PLightDevice::getDay, 1).orderByDesc(PLightDevice::getCreateTime).last("LIMIT 1"));
  19.         PLightDevice lastData = lightDeviceDao.selectOne(new LambdaQueryWrapper<>(PLightDevice.class).eq(PLightDevice::getYear, localDateTime.getYear())
  20.                 .eq(PLightDevice::getMonth, localDateTime.getMonth()).eq(PLightDevice::getDay, localDateTime.getDayOfMonth()).orderByDesc(PLightDevice::getCreateTime).last("LIMIT 1"));
  21.         //总用电量
  22.         BigDecimal zero = BigDecimal.ZERO;
  23.         if (lastData != null) {
  24.             zero = lastData.getTotalUsage();
  25.             if (firstData != null) {
  26.                 zero = zero.subtract(firstData.getTotalUsage()).setScale(0, RoundingMode.DOWN);
  27.             }
  28.         }
  29.         row2.createCell(1).setCellValue(Long.parseLong(zero.setScale(0, RoundingMode.DOWN).toString()));
  30.         //昨日日期减2023年5月1日
  31.         long daysBetween = ChronoUnit.DAYS.between(LocalDate.of(2023, 5, 1), LocalDate.now());
  32.         BigDecimal avgEveryDay = zero.divide(BigDecimal.valueOf(daysBetween), 2, RoundingMode.HALF_UP);
  33.         Row row3 = overview.createRow(2);
  34.         row3.createCell(0).setCellValue("平均每日用电量(kwh)");
  35.         row3.createCell(1).setCellValue(Double.parseDouble(avgEveryDay.toString()));
  36.         Row row4 = overview.createRow(3);
  37.         row4.createCell(0).setCellValue("其中光伏电用量(kwh)");
  38.         BigDecimal lightZero = BigDecimal.ZERO;
  39.         BigDecimal nationZero = BigDecimal.ZERO;
  40.         if (lastData != null) {
  41.             lightZero = lastData.getLightUsage();
  42.             nationZero = lastData.getCountryUsage();
  43.             if (firstData != null) {
  44.                 nationZero = nationZero.subtract(firstData.getCountryUsage()).setScale(0, RoundingMode.DOWN);
  45.                 lightZero = lightZero.subtract(firstData.getLightUsage()).setScale(0, RoundingMode.DOWN);
  46.             }
  47.         }
  48.         row4.createCell(1).setCellValue(Long.parseLong(lightZero.setScale(0, RoundingMode.DOWN).toString()));
  49.         row4.createCell(2).setCellValue("占比");
  50.         row4.createCell(3).setCellValue(lightZero.multiply(oneHundrend).divide(lightZero.add(nationZero), 0, RoundingMode.HALF_UP) + "%");
  51.         row4.createCell(4).setCellValue("折算碳减排(kgCO2e)");
  52.         row4.createCell(5).setCellValue(Double.parseDouble(lightZero.multiply(ligthRation).setScale(2, RoundingMode.HALF_UP).toString()));
  53.         Row row5 = overview.createRow(4);
  54.         row5.createCell(0).setCellValue("其中国网用电量(kwh)");
  55.         row5.createCell(1).setCellValue(Long.parseLong(nationZero.setScale(0, RoundingMode.DOWN).toString()));
  56.         row5.createCell(2).setCellValue("占比");
  57.         row5.createCell(3).setCellValue(nationZero.multiply(oneHundrend).divide(lightZero.add(nationZero), 0, RoundingMode.HALF_UP) + "%");
  58.         row5.createCell(4).setCellValue("折算碳减排(kgCO2e)");
  59.         row5.createCell(5).setCellValue(Double.parseDouble(nationZero.multiply(ligthRation).setScale(2, RoundingMode.HALF_UP).toString()));
  60.         Row row6 = overview.createRow(5);
  61.         row6.createCell(0).setCellValue("法庭单日最大用电量(kwh)");
  62.         //查询每一天的最后一条数据
  63.         List<PLightDevice> list = baseMapper.selectEveryDayData();
  64.         //计算最大的一天的用电量
  65.         // 计算当日使用量并找出最大的一天
  66.         BigDecimal maxUsage = BigDecimal.ZERO;
  67.         BigDecimal lightMaxUsage = BigDecimal.ZERO;
  68.         LocalDateTime lightMaxUsageData = null;
  69.         for (int i = 1; i < list.size(); i++) {
  70.             PLightDevice prev = list.get(i - 1);
  71.             PLightDevice current = list.get(i);
  72.             LocalDate currentLocalDate = LocalDate.of(current.getYear(), current.getMonth(), current.getDay()).minusDays(1);
  73.             LocalDate preLocalDate = LocalDate.of(prev.getYear(), prev.getMonth(), prev.getDay());
  74.             //判断两个时间想等 如果有时间间隔就跳过
  75.             if (!currentLocalDate.equals(preLocalDate)) {
  76.                 continue;
  77.             }
  78.             // 计算当日使用量
  79.             BigDecimal dailyUsage = current.getTotalUsage().subtract(prev.getTotalUsage());
  80.             BigDecimal lightDailyUsage = current.getLightUsage().subtract(prev.getLightUsage());
  81.             // 查找最大使用量
  82.             if (dailyUsage.compareTo(maxUsage) == 1) {
  83.                 maxUsage = dailyUsage;
  84.             }
  85.             // 查找最大光伏用电量
  86.             if (lightDailyUsage.compareTo(lightMaxUsage) == 1) {
  87.                 lightMaxUsage = lightDailyUsage;
  88.                 lightMaxUsageData = current.getCreateTime();
  89.             }
  90.         }
  91.         //判断第一天的数据和最大数据谁更大
  92.         PLightDevice pLightDevice = list.get(0);
  93.         if (pLightDevice != null) {
  94.             if (pLightDevice.getTotalUsage().compareTo(maxUsage) == 1) {
  95.                 maxUsage = pLightDevice.getTotalUsage();
  96.             }
  97.         }
  98.         row6.createCell(1).setCellValue(Long.parseLong(maxUsage.setScale(0, RoundingMode.DOWN).toString()));
  99.         Row row7 = overview.createRow(6);
  100.         row7.createCell(0).setCellValue("光伏单日最大发电量(kwh)");
  101.         row7.createCell(1).setCellValue(Long.parseLong(lightMaxUsage.setScale(0, RoundingMode.DOWN).toString()));
  102.         row7.createCell(2).setCellValue("出现日期");
  103.         if (lightMaxUsageData != null) {
  104.             row7.createCell(3).setCellValue(lightMaxUsageData.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
  105.         }
  106.         //设置第一行的样式
  107.         setHeaderStyle(workbook, overview);
  108.     }
复制代码
  1.     private void handeleMonthAvgDay(Workbook workbook) {
  2.         Sheet monthAvgDay = workbook.createSheet("每月平均日光伏发电量");
  3.         LocalDate now = LocalDate.now();
  4.         //获取每个月最后一天的数据
  5.         List<PLightDevice> list = baseMapper.selectEveryMonthData();
  6.         Row row = monthAvgDay.createRow(0);
  7.         row.createCell(0).setCellValue("月份");
  8.         row.createCell(1).setCellValue("平均每日发电量");
  9.         row.createCell(2).setCellValue("发电天数");
  10.         row.createCell(3).setCellValue("总发电量");
  11.         //总发电天数
  12.         int totalDay = 0;
  13.         //总发电量
  14.         BigDecimal totalUsage = BigDecimal.ZERO;
  15.         for (int i = 0; i < list.size(); i++) {
  16.             Row rowi = monthAvgDay.createRow(i + 1);
  17.             PLightDevice current = list.get(i);
  18.             rowi.createCell(0).setCellValue(current.getYear() + "-" + current.getMonth());
  19.             if (i == 0) {
  20.                 //当月的总天数
  21.                 int allDay = LocalDate.of(current.getYear(), current.getMonth(), 1).lengthOfMonth();
  22.                 totalDay += allDay;
  23.                 rowi.createCell(1).setCellValue(Double.parseDouble(current.getLightUsage().divide(BigDecimal.valueOf(allDay), 2, RoundingMode.HALF_UP).toString()));
  24.                 rowi.createCell(2).setCellValue(allDay);
  25.                 rowi.createCell(3).setCellValue(Long.parseLong(current.getLightUsage().setScale(0, RoundingMode.DOWN).toString()));
  26.                 totalUsage = totalUsage.add(current.getLightUsage());
  27.                 continue;
  28.             }
  29.             //上一个月的数据
  30.             PLightDevice prev = list.get(i - 1);
  31.             // 计算当月使用量
  32.             BigDecimal lightDailyUsage = current.getLightUsage().subtract(prev.getLightUsage());
  33.             //当月发电天数
  34.             int allDay;
  35.             if (now.getMonthValue() != current.getMonth()) {
  36.                 allDay = LocalDate.of(current.getYear(), current.getMonth(), 1).lengthOfMonth();
  37.             } else {
  38.                 allDay = now.getDayOfMonth();
  39.             }
  40.             rowi.createCell(1).setCellValue(Double.parseDouble(lightDailyUsage.divide(BigDecimal.valueOf(allDay), 2, RoundingMode.HALF_UP).toString()));
  41.             rowi.createCell(2).setCellValue(allDay);
  42.             rowi.createCell(3).setCellValue(Long.parseLong(lightDailyUsage.setScale(0, RoundingMode.DOWN).toString()));
  43.             //累加值
  44.             totalDay += allDay;
  45.             totalUsage = totalUsage.add(lightDailyUsage);
  46.         }
  47.         int lastRowNum = monthAvgDay.getLastRowNum() + 1;
  48.         Row lastRow = monthAvgDay.createRow(lastRowNum);
  49.         lastRow.createCell(0).setCellValue("总计");
  50.         lastRow.createCell(1).setCellValue(Double.parseDouble(totalUsage.divide(BigDecimal.valueOf(totalDay), 2, RoundingMode.HALF_UP).toString()));
  51.         lastRow.createCell(2).setCellValue(totalDay);
  52.         lastRow.createCell(3).setCellValue(Long.parseLong(totalUsage.setScale(0, RoundingMode.DOWN).toString()));
  53.         setHeaderStyle(workbook,monthAvgDay);
  54.     }
复制代码
  1.     private void handeleMonthLightUsageRation(Workbook workbook) {
  2.         Sheet monthLightUsageRation = workbook.createSheet("每月光伏用电量占比");
  3.         //获取每个月最后一天的数据
  4.         List<PLightDevice> list = baseMapper.selectEveryMonthData();
  5.         Row row = monthLightUsageRation.createRow(0);
  6.         row.createCell(0).setCellValue("月份");
  7.         row.createCell(1).setCellValue("总用电量");
  8.         row.createCell(2).setCellValue("光伏用电量");
  9.         row.createCell(3).setCellValue("占比");
  10.         row.createCell(4).setCellValue("国网用电量");
  11.         row.createCell(5).setCellValue("占比");
  12.         for (int i = 0; i < list.size(); i++) {
  13.             Row rowi = monthLightUsageRation.createRow(i + 1);
  14.             PLightDevice current = list.get(i);
  15.             rowi.createCell(0).setCellValue(current.getYear() + "-" + current.getMonth());
  16.             if (i == 0) {
  17.                 //当月的总天数
  18.                 rowi.createCell(1).setCellValue(Long.parseLong(current.getTotalUsage().setScale(0, RoundingMode.DOWN).toString()));
  19.                 rowi.createCell(2).setCellValue(Long.parseLong(current.getLightUsage().setScale(0, RoundingMode.DOWN).toString()));
  20.                 rowi.createCell(3).setCellValue(current.getLightUsage().multiply(oneHundrend).divide(current.getTotalUsage(), 0, RoundingMode.HALF_UP)+"%");
  21.                 rowi.createCell(4).setCellValue(Long.parseLong(current.getCountryUsage().setScale(0, RoundingMode.DOWN).toString()));
  22.                 rowi.createCell(5).setCellValue(current.getCountryUsage().multiply(oneHundrend).divide(current.getTotalUsage(), 0, RoundingMode.HALF_UP)+"%");
  23.                 continue;
  24.             }
  25.             //上一个月的数据
  26.             PLightDevice prev = list.get(i - 1);
  27.             // 计算当月使用量
  28.             BigDecimal totalUsage = current.getTotalUsage().subtract(prev.getTotalUsage());
  29.             BigDecimal lightDailyUsage = current.getLightUsage().subtract(prev.getLightUsage());
  30.             BigDecimal contryUsage = current.getCountryUsage().subtract(prev.getCountryUsage());
  31.             rowi.createCell(1).setCellValue(Long.parseLong(totalUsage.setScale(0, RoundingMode.DOWN).toString()));
  32.             rowi.createCell(2).setCellValue(Long.parseLong(lightDailyUsage.setScale(0, RoundingMode.DOWN).toString()));
  33.             rowi.createCell(3).setCellValue(lightDailyUsage.multiply(oneHundrend).divide(totalUsage, 0, RoundingMode.HALF_UP)+"%");
  34.             rowi.createCell(4).setCellValue(Long.parseLong(contryUsage.setScale(0, RoundingMode.DOWN).toString()));
  35.             rowi.createCell(5).setCellValue(contryUsage.multiply(oneHundrend).divide(totalUsage, 0, RoundingMode.HALF_UP)+"%");
  36.         }
  37.         setHeaderStyle(workbook,monthLightUsageRation);
  38.     }
复制代码
 
 这是设置我须要的格式的代码
  1.     private void setHeaderStyle(Workbook workbook,Sheet sheet){
  2.         // 创建样式对象
  3.         CellStyle headerStyle = workbook.createCellStyle();
  4.         // 设置居中对齐和自动换行
  5.         headerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
  6.         headerStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中
  7.         headerStyle.setWrapText(true); // 启用自动换行
  8.         // 创建一个字体对象,设置加粗(Bold)
  9.         Font font = workbook.createFont();
  10.         font.setBold(true); // 设置加粗
  11.         headerStyle.setFont(font);
  12.         headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); // 灰色背景
  13.         headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 填充方式为实心填充
  14.          Row firstRow = sheet.getRow(0); // 第一行的索引是 0
  15.          // 给第一行的所有单元格应用该样式
  16.         if (firstRow != null) {
  17.             for (Cell cell : firstRow) {
  18.                 cell.setCellStyle(headerStyle); // 设置单元格样式
  19.             }
  20.         }
  21.     }
复制代码
 


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表