Day12-苍穹外卖(完结篇)

前言:

今天写Day12的内容。也是最后一天的课程内容。

今日所学:

  • Apache POI
  • 导出运营数据Excel报表

1. Apache POI

1.1 介绍

Apache POI(Poor Obfuscation Implementation的递归缩写)是一个开源的Java API,用于处理Microsoft Office格式文件。它允许Java程序读取、写入和操作Microsoft Office文档,包括Excel、Word和PowerPoint文件。

一句话总结:

Apache POI是一个用于读写Microsoft Office格式文件(如Excel、Word、PPT)的Java开源库。

1.2 如何在Java项目中使用

这里以读写excel表格为例

1.2.1. 引入相关的依赖

先是基础依赖

另外还有excel支持依赖

1.2.2. 对excel表格进行读写操作

导入相应的坐标就可以对excel表格进行读写操作了

这里我们先讲写操作

1. 内存中创建一个Excel文件

2.在excel文件中创建一个sheet页

3.在sheet页中指定行,并且给指定行的指定单元格赋值(这里注意行和单元格的索引都是从零开始的,也就是零是第一行)

4.通过数据流fileout将excel表格写入到磁盘,并关闭相应操作

具体代码

/**
 * 通过POI去写Excel文件
 * @throws IOException
 */
public static void write() throws IOException {
    // 在内存张创建一个Excel文件
    XSSFWorkbook workbook = new XSSFWorkbook();
    // 在excel文件中创建一个sheet页
    XSSFSheet sheet = workbook.createSheet("info");
    // sheet中创建对象,Row编号从零开始
    XSSFRow row = sheet.createRow(0);
    row.createCell(0).setCellValue("姓名");
    row.createCell(1).setCellValue("城市");

    row = sheet.createRow(1);
    row.createCell(0).setCellValue("张三");
    row.createCell(1).setCellValue("南京");

    row = sheet.createRow(2);
    row.createCell(0).setCellValue("李四");
    row.createCell(1).setCellValue("芜湖");

    // 通过数据流将内存中的ECcel文件给它写入到磁盘
    FileOutputStream fileOut = new FileOutputStream("D:\\ExcelData\\info.xlsx");
    workbook.write(fileOut);
    fileOut.close();
    workbook.close();
}
public static void main(String[] args) throws Exception {
    //read();
     write();
}

接下来是读操作

1. 通过输入流传入相应的文件给excel对象

2.获得想读取数据的那一页sheet,并获得载有数据的最后一行

3. 从第一行开始遍历row,获得每一行的数据并输出

4.关闭相应操作

具体代码:

/**
 * 通过POI去读取Excel文件
 * @throws IOException
 */
public static void read() throws IOException {
    // 创建excel对象,找到相应的excel表格
    FileInputStream fileIn = new FileInputStream("D:\\ExcelData\\info.xlsx");
    XSSFWorkbook workbook = new XSSFWorkbook(fileIn);
    XSSFSheet sheet = workbook.getSheetAt(0);
    // 获得最后一行
    int lastRowNum = sheet.getLastRowNum();

    // 遍历
    for (int i = 0; i <= lastRowNum; i++) {
        XSSFRow row = sheet.getRow(i);
        if (row != null) {
            String stringCellValue = row.getCell(0).getStringCellValue();
            String stringCellValue1 = row.getCell(1).getStringCellValue();
            System.out.println(stringCellValue + " " + stringCellValue1);
        }
    }
    fileIn.close();
    workbook.close();
}


public static void main(String[] args) throws Exception {
    read();
    // write();
}

运行效果:

2.导出运营数据Excel报表

需求分析:

业务规则:

  • 导出Excel形式的报表文件
  • 导出最近30天的运营数据
  • 导出最近30天每日的明细数据

需要注意的是这个接口功能不传入和返回任何数据

代码展示:

admin包下的ReportController类下(Controller层)写入以下代码:

/**
 * 导出运营数据报表
 * @param response
 * @return
 */
@GetMapping("/export")
@ApiOperation("导出运营数据报表")
public void export(HttpServletResponse response){
    reportService.exportBusinessData(response);
}

要注意的是虽然接口不传入任何参数,但是我们可以传入一个httpServletResponse用于将excel文件下载到客户端浏览器

service层:

具体的代码逻辑:

1. 将时间回溯到30天前,查看30天前到现在的营业数据(营业额,订单完成率,新增用户数,有效订单,平均客单价,这些都是封装到BusinessDataVo的数据)

2. 通过POI写入到Excel文件中(填充概览数据->30天的总数据

先是通过输入流传入相应的文件给excel对象(这边输入流加载文件用的是类加载器),调用workspaceService.getBusinessData方法,最后获取sheet->row->填充相应的ceil单元格

3.通过POI写入到Excel文件中(填充明细数据->30天内每天的数据

在前一步excel对象的基础上,for循环得到30天内每天的日期,将其依次调用workspaceService.getBusinessData方法,获取sheet->row->填充相应的ceik单元格

4.通过输出流将Excel文件下载到相应的客户端浏览器

5.关闭相应资源

/**
 * 导出运营数据报表
 * @param response
 */
@Override
public void exportBusinessData(HttpServletResponse response) {
    // 1, 查询数据库,获取营业数据 ... 查询30天的运营数据
    // 前面30天
    LocalDate begin = LocalDate.now().minusDays(30);

    LocalDate end = LocalDate.now().minusDays(1);

    LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);

    LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);

    BusinessDataVO businessData = workspaceService.getBusinessData(beginTime, endTime);
    // 2.通过POI写入到Excel文件中
    InputStream in = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");

    try {
        // 基于模板文件创建一个新的Excel文件
        XSSFWorkbook workbook = new XSSFWorkbook(in);

        // 获取表格的sheet页面
        XSSFSheet sheet = workbook.getSheetAt(0);

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

        // 获得第4行
        XSSFRow row = sheet.getRow(3);
        row.getCell(2).setCellValue(businessData.getTurnover());
        row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
        row.getCell(6).setCellValue(businessData.getNewUsers());

        // 获得第5行
        XSSFRow row1 = sheet.getRow(4);
        row1.getCell(2).setCellValue(businessData.getValidOrderCount());
        row1.getCell(4).setCellValue(businessData.getUnitPrice());

        // 填充我们的明细数据
        for (int i = 0; i < 30; i++) {
            begin = begin.plusDays(i);
            BusinessDataVO businessDataVO = workspaceService.getBusinessData(LocalDateTime.of(begin, LocalTime.MIN), LocalDateTime.of(begin, LocalTime.MAX));
            // 接收每一行的数据
            XSSFRow row2 = sheet.getRow(7 + i);

            // 获取单元格
            row2.getCell(1).setCellValue(begin.toString());
            row2.getCell(2).setCellValue(businessDataVO.getTurnover());
            row2.getCell(3).setCellValue(businessDataVO.getValidOrderCount());
            row2.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());
            row2.getCell(5).setCellValue(businessDataVO.getUnitPrice());
            row2.getCell(6).setCellValue(businessDataVO.getNewUsers());


        }
        // 3.通过输出流将Excel文件下载到客户端浏览器
        ServletOutputStream outputStream = response.getOutputStream();
        workbook.write(outputStream);
        // 关闭资源
        outputStream.flush();
        outputStream.close();
        workbook.close();
    }catch (Exception e) {
        e.printStackTrace();
    }
}

这里都是调用写好的方法,所以没有用到mapper层

问题:

1.在Controller层我将result.success()作为了返回数据

导致生成的excel文件是这样的

2.在关闭输出流outputStream时,没有使用flush强制将缓冲区的数据写入目标

导致生成的excel文件是空的

最后:

今天的分享就到这里。如果我的内容对你有帮助,请点赞评论收藏。创作不易,大家的支持就是我坚持下去的动力!(๑`・ᴗ・´๑)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值