通过POI 根据excel模板导出excel

405 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

theme: condensed-night-purple

封面

cat.jpg 这是我的宝贝猫咪和大家见个面!!!

问题背景

项目中需要导出一个excel,这不是一个普通的excel;会根据数据生成饼图。

  • 这里就遇到几个问题:
  1. 导出的数据在excel的每一个单元格的左上角带一个绿色的小三角;
  2. 导出后点饼图不生效需要双击任意单元格才生效
  3. 因为是模板导出所以应该是创建单元格而不是给单元格赋值

效果图

image.png

最终代码

// 查询到需要生成饼图的数据
List<DTO> list = dao.list(params);
// 获取当前系统时间
Date date = cn.hutool.core.date.DateUtil.date();
String format = cn.hutool.core.date.DateUtil.format(date, "yyyy/MM/dd");
// 设置导出文件的名称
String fileName = "饼图_" + format;
// 获取模板路径(建议excel模板的名称为英文以防出现莫名的问题)
String path = "templates/report/RAMP_BOARD.xlsx";
// 读取模板
ClassPathResource resource = new ClassPathResource(path);
// 创建excel
Workbook workbook = WorkbookFactory.create(resource.getStream());
// 获取到第一个sheet
Sheet sheet = workbook.getSheetAt(0);
// 设置模板内的excel函数生效
sheet.setForceFormulaRecalculation(true);
// 设置为非保护视图(这个没有生效有知道的小伙伴分享一下)
workbook.setActiveSheet(0);
// 从第15行开始写入数据——因为我的饼图在开头所以不能从第一行开始写数据
int rowNum = 15;
for (int i = 0; i < list.size(); i++) {
    // 给sheet中创建行
    Row row = sheet.createRow(rowNum + i);
    // 小数
    if (list.get(i).getDouble() != null) {
        // 创建单元格样式
        CellStyle cellStyle = workbook.createCellStyle();
        // 数据格式
        DataFormat dataFormat = workbook.createDataFormat();
        cellStyle.setDataFormat(dataFormat.getFormat("0.00"));
        cellStyle.setAlignment(HorizontalAlignment.RIGHT);
        // 这里注意:因为导出的是小数所以这里用Double否则会引发问题2
        Double caseName = Double.valueOf(list.get(i).getBetaCoefficient());
        // 给这一行创建第6个单元格
        Cell cell = row.createCell(6);
        // 给单元格填入数据
        cell.setCellStyle(cellStyle);
        // 设置单元格样式
        cell.setCellValue(caseName);
    } else {
        row.createCell(6).setCellValue("");
    }

    // 百分数
    if (list.get(i).getRValue() != null) {
        // 创建单元格样式
        CellStyle cellStyle = workbook.createCellStyle();
        // 数据格式
        cellStyle.setDataFormat((short) BuiltinFormats.getBuiltinFormat("0.00%"));
        cellStyle.setAlignment(HorizontalAlignment.RIGHT);
        // 获取数据——这里应该传入的是小数,设置的数据格式会自动转为百分数
        String caseName = list.get(i).getRValue();
        Cell cell = row.createCell(9);
        cell.setCellStyle(cellStyle);
        // 判断导出的是不是小数——我这里会出现小数和--
        if (caseName.equals("--")) {
            cell.setCellValue(caseName);
        } else {
            cell.setCellValue(new BigDecimal(caseName).doubleValue());
        }
    } else {
        row.createCell(9).setCellValue("");
    }
}

引入的POI版本

<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-base</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-web</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-annotation</artifactId>
    <version>4.1.0</version>
</dependency>