EasyExcel第三弹 + hutool-poi 配合使用导出较复杂Excel.xlsx + 计算增长率、同比环比、比重等_王德发!的博客-CSDN博客

一、回顾

继上次“动态表头easyExcel导入导出https://blog.csdn.net/qq_37337660/article/details/114680512)”,
和上上次“动态表头导入https://blog.csdn.net/qq_37337660/article/details/110288393)”之后。
我们迎来了第三波easyExcel的_折磨_,这次导出复杂的Excel,顺便用了hutool里面的Excel功能。(超链接链接到的是官网)
1.第一步是设计模板,利用模板导出一份新的xlsx;
2.第二步是利用hutool把新的xlsx读取,然后往里加数据,同时调整格式,合并单元格,改动sheet名称等。

需求:导出:多页sheet、复杂表头、sheet名称改动、单元格合并、简单格式调整
sheet0
分析:以上这个sheet0的格式要求,可以看出前面几列的格式非常复杂且固定、表头也是相对固定。我们只要把剩下的空白格子和标题利用填充的办法就可以搞定。模板如下:
在这里插入图片描述

二、easyExcel的填充功能

官网填充:https://www.yuque.com/easyexcel/doc/fill
这此就少说废话了,代码都加上了注释

private String doFill() {
        String fileName = unit.getShortname() + startTime + "—" + endTime + "导出.xlsx";
        // 指定新文件的路径和名称
        File file = new File(FORM_STORE_PATH + fileName);
        if (!file.getParentFile().exists()) {
            boolean mkdirs = file.getParentFile().mkdirs();
        }
        String newFile = file.getPath();
        // 这里是填充的模板,放到resource下
        InputStream template = this.getClass().getResourceAsStream("/template/模板.xlsx");
        com.alibaba.excel.ExcelWriter excelWriter = EasyExcel.write(newFile).withTemplate(template).build();
        // 开始填充(我这里有8个sheet,每一个里面都有标题动态填充。这里先把标题填充好,把sheet0、2的内容填充好)
        for (int sheetNo = 0; sheetNo < 8; sheetNo++) {
            WriteSheet writeSheet = EasyExcelFactory.writerSheet(sheetNo).build();
            writeSheet.setSheetName(getSheetNameBySheetNo(sheetNo));
            FillConfig fillConfig =
                    FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();
            excelWriter.fill(
                    new FillWrapper("CommonTitle", Collections.singleton(title)),// 这个就是模板里面的前缀
                    fillConfig,
                    writeSheet);
            switch (sheetNo) {
                case 0:
                    excelWriter.fill(
                            new FillWrapper("data", getData()),// "data"这个就是模板里面的前缀
                            writeSheet);
                    break;
                case 2:
                    excelWriter.fill(
                            new FillWrapper("data", getData()),// 这个就是模板里面的前缀
                            writeSheet);
                    break;
                default:
                    break;
            }
        }
        excelWriter.finish();
        return fileName;
    }
//这里严格按照定义的顺序封装数据。list有几行,就会往下填充几行(当然也可以用map装数据,可以看看官网怎么用的)
private List<Sheet02Statistic> getData() {}
//实体类定义如下
public class Sheet02Statistic {
    /** 本期 */
    private Long bq;
    /** 上期 */
    private Long sq;
    /** 本期增长率 */
    private String bqRate;
    /** 去年同期 */
    private Long qntq;
    /** 去年同期增长率 */
    private String qntqRate;
    /** 今年以来 */
    private Long jnyl;
    /** 今年以来增长率 */
    private String jnylRate;
}

三、hutool的Excel生成-ExcelWriter

各类用法参考官网:https://www.hutool.cn/docs/#/poi/Excel%E7%94%9F%E6%88%90-ExcelWriter
原始第8个sheet:
在这里插入图片描述
通过下面代码生成后的:
在这里插入图片描述

这里截取部分代码:

// newFilePath 是刚刚用模板生成的文件的路径
private void doWrite(String newFilePath) {
        cn.hutool.poi.excel.ExcelWriter writer = ExcelUtil.getWriter(newFilePath);
        writeSheet1(writer);
        writeSheet3(writer);
        writeSheet5(writer);
        writeSheet6(writer);
        writeSheet7(writer);
        writeSheet8(writer);
        //这里改sheet名称
        writer.renameSheet(0, title.getSheet0());
        writer.renameSheet(1, title.getSheet1());
        writer.renameSheet(2, title.getSheet2());
        writer.renameSheet(7, title.getSheet7());
        //如果有用了公式,用这个来使公式生效
        Workbook workbook = writer.getWorkbook();
        workbook.setForceFormulaRecalculation(true);
        writer.close();
    }
    
private void writeSheet8(cn.hutool.poi.excel.ExcelWriter writer) {
        //设置字体
        Font font = writer.createFont();
        font.setFontName("黑体");
        font.setFontHeightInPoints((short) 12);
        //设置头样式。去除背景setFillPattern
        CellStyle headCellStyle = writer.getHeadCellStyle();
        headCellStyle.setFillPattern(FillPatternType.NO_FILL);
        headCellStyle.setFont(font);
        headCellStyle.setBorderTop(BorderStyle.NONE);
        headCellStyle.setBorderRight(BorderStyle.NONE);
        headCellStyle.setAlignment(HorizontalAlignment.LEFT);
        List<Sheet8Statistic> data1 = getSheet8StatisticData(1);
        writer.setSheet(8);
        //跳过前的几行
        writer.passRows(4);
        //写入表1的内容
        writer.write(data1);
        //表1写完了,再跳一行
        writer.passRows(1);
        //生成第二张表的表头信息。合并单元格
        writer.merge(5 + data1.size(), 5 + data1.size(), 0, 7, "(三)标题", true);
        writer.merge(6 + data1.size(), 7 + data1.size(), 0, 0, "", false);
        writer.merge(6 + data1.size(), 7 + data1.size(), 1, 1, "本期", false);
        writer.merge(6 + data1.size(), 6 + data1.size(), 2, 3, "上期", false);
        writer.merge(6 + data1.size(), 6 + data1.size(), 4, 5, "去年同期", false);
        writer.merge(6 + data1.size(), 6 + data1.size(), 6, 7, "今年以来", false);
        //跳过刚刚的表头信息行
        writer.passRows(2);
        List<Sheet8Statistic> data2 = getSheet8StatisticData(2);
        data2.add(0, new Sheet8Statistic("无", "本期", "件", "±%", "件", "±%", "件", "±%"));
        writer.write(data2);
    }
//这里严格按照定义的顺序封装数据。list有几行,就会往下填充几行(当然也可以用map装数据,可以看看官网怎么用的)
private List<Sheet8Statistic> getSheet8StatisticData(int tableNo) {}
//实体类定义如下
public class Sheet8Statistic {
    /** 地区 */
    private Object area;
    /** 本期 */
    private Object bq;
    /** 上期 */
    private Object sq;
    /** 本期增长率 */
    private Object bqRate;
    /** 去年同期 */
    private Object qntq;
    /** 去年同期增长率 */
    private Object qntqRate;
    /** 今年以来 */
    private Object jnyl;
    /** 今年以来增长率 */
    private Object jnylRate;
}
    • *

到这里写入的数据都差不多了,有问题或不对的地方欢迎评论指教。利用easyExcel的填充功能,和hutool的写入功能完成一份报表的导出。需要注意的是我这边数据很小无所谓,hutool这个是先把所有数据都写入内存,最后再写入文件的,数据太大就要再处理了,官网也提到了多次写入的办法那些。

下面附上一些用到的常用方法:

四、计算增长率、同比环比、比重等

/**
     * 计算增长率 2位小数
     *
     * @param bq 本期
     * @param sq 上期
     */
    protected String calculateRate(Long bq, Long sq) {
        DecimalFormat df = new DecimalFormat("0.00");
        if (sq == 0) {
            return "0";
        }
        return df.format((float) (bq - sq) / sq * 100);
    }


    /**
     * 计算同比、环比、比重
     *
     * @param bq 本期
     * @param sq 上期
     */
    protected static String calculateTbHb(Long bq, Long sq) {
        if (sq == 0) {
            return "0";
        }
        BigDecimal bqBigDecimal = BigDecimal.valueOf(bq);
        BigDecimal sqBigDecimal = BigDecimal.valueOf(sq);
        BigDecimal result =
                (bqBigDecimal.subtract(sqBigDecimal))
                        .divide(sqBigDecimal, 4, BigDecimal.ROUND_UP)
                        .multiply(BigDecimal.valueOf(100L))
                        .setScale(2, BigDecimal.ROUND_UP);
        if (result.compareTo(BigDecimal.ZERO) > 0) {
            return "+" + result.doubleValue();
        } else if (result.compareTo(BigDecimal.ZERO) < 0) {
            return String.valueOf(result.doubleValue());
        } else {
            return "0";
        }
    }

原网址: 访问
创建于: 2021-11-08 11:15:28
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论