Apache POI 实战应用:企业级文档处理解决方案

发布于:2025-07-26 ⋅ 阅读:(13) ⋅ 点赞:(0)

在企业级应用中,数据报表导出是核心功能之一。本文将解析一个基于Java实现的运营数据报表导出功能,该功能可导出近30天(不含当日)的详细业务数据到Excel表格中。


一、功能设计
  1. 时间范围:近30天(从T-30天到昨天)

  2. 数据内容

    • 汇总数据:营业额、订单完成率、新增用户等

    • 每日明细:日期、营业额、有效订单等

  3. 技术栈

    • Java 8日期时间API

    • Apache POI处理Excel

    • Spring Web响应流输出


二、核心代码解析
    /**
     * 导出近30天内的数据统计 Excel表
     * @param response
     */
    public void getExport(HttpServletResponse response) {
        //1.查询数据库30天内(不包含今天)的营业相关数据

        //30天前---昨天
        LocalDate begin=LocalDate.now().minusDays(30);
        LocalDate end=LocalDate.now().minusDays(1);

        //获取30天前的最小时间和昨天的最大时间
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);

        //获取相关数据
        BusinessDataVO dataVO = workspaceService.getBusinessData(beginTime, endTime);

        //2.通过POI将数据写入Excel表

        //获取表
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");

        try {
            //获取excel
            XSSFWorkbook excel=new XSSFWorkbook(in);

            //获取sheet页
            XSSFSheet sheet=excel.getSheet("Sheet1");

            //填充数据--时间
            sheet.getRow(1).getCell(1).setCellValue("时间:"+begin+"至"+end);

            //获得第四行
            XSSFRow row=sheet.getRow(3);
            //添加营业额
            row.getCell(2).setCellValue(dataVO.getTurnover());
            //订单完成率
            row.getCell(4).setCellValue(dataVO.getOrderCompletionRate());
            //新增用户数
            row.getCell(6).setCellValue(dataVO.getNewUsers());

            //获取第五行
            row=sheet.getRow(4);
            //有效订单数
            row.getCell(2).setCellValue(dataVO.getValidOrderCount());
            //平均客单价
            row.getCell(4).setCellValue(dataVO.getUnitPrice());


            //填充明细数据
            for (int i = 0; i < 30; i++) {
                LocalDate date=begin.plusDays(i);
                //查询当前data的营业数据
                BusinessDataVO businessDataVO = workspaceService.getBusinessData(LocalDateTime.of(date, LocalTime.MIN), LocalDateTime.of(date, LocalTime.MAX));

                //获取某行
                row=sheet.getRow(7+i);
                row.getCell(1).setCellValue(date.toString());
                row.getCell(2).setCellValue(businessDataVO.getTurnover());
                row.getCell(3).setCellValue(businessDataVO.getValidOrderCount());
                row.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());
                row.getCell(5).setCellValue(businessDataVO.getUnitPrice());
                row.getCell(6).setCellValue(businessDataVO.getNewUsers());

            }

            //3.通过输出流讲Excel文件下载到客户带
            ServletOutputStream out=response.getOutputStream();
            excel.write(out);

        } catch (IOException e) {
            throw new RuntimeException("导出失败,请重试");
        }
    }

三、关键技术点详解
  1. 时间范围计算

    LocalDate.now().minusDays(30) // 动态计算30天前日期
    LocalTime.MIN/MAX // 获取全天时间范围
  2. Excel模板操作

    • 使用预置模板保证格式规范

    • 按坐标填充数据:

      sheet.getRow(3).getCell(2).setCellValue(dataVO.getTurnover())
  3. 每日数据填充

    for (int i = 0; i < 30; i++) {
        LocalDate date = begin.plusDays(i);
        BusinessDataVO dailyData = workspaceService.getDailyData(date);
        // 填充到第7+i行...
    }
  4. 流式输出优化

response.setContentType("application/vnd.openxmlformats...");
excel.write(response.getOutputStream()); // 避免内存溢出
五、模板设计示例
单元格 内容 数据源
B2 时间范围 begin ~ end
C4 营业额 dataVO.turnover
C8~C37 每日营业额 dailyData
D8~D37 每日有效订单数 dailyData
七、总结

该实现通过:

  1. 动态时间范围计算

  2. 模板化Excel操作

  3. 流式响应输出

  4. 分层数据填充

实现了高效可靠的报表导出功能。实际部署中建议增加:

  • 导出任务队列

  • 进度查询接口

  • 大数据量分页处理

关键优势:
✅ 保证数据时效性
✅ 保持专业报表格式
✅ 避免内存溢出风险
✅ 支持高并发场景


网站公告

今日签到

点亮在社区的每一天
去签到