基于POI的可快速定制Excel导出脚本设想

本文提出了一种使用JSON+SQL实现的可快速定制的Excel导出脚本,旨在解决业务人员紧急但不常用的数据取数需求。通过解析JSON配置文件,动态执行SQL并按需分组数据,生成超大规模分组的Excel文件。代码实现了数据拆分和分组导出两大功能,有效应对大规模数据处理挑战。
摘要由CSDN通过智能技术生成

基于POI的可快速定制Excel导出脚本设想

背景

  年关将至,业务人员提出了好多比较着急但是又不常用的取数需求。所谓不常用,大概了是由于业务人员前期调研产生的临时需求,后续也不会大面积铺开,没必要专门分配人员去开发。所谓比较着急,开发人员开发出来需要一段时间,等到投产窗口投产又得一段时间,一定程度上可能错过这个市场机遇,基于此,提出这个设想。

  目前从网络上所查到的方法都是基于poi去实现的,且实现方法比较简单,不太适用于比较复杂的业务场景(超大规模数据导出(一个excel装不下),大规模数据分组(以千为单位)导出等),秉承着“用户至上”的原则,急业务人员之所急,想业务人员之所想,于是便提出了如此设想。

  为了能够满足可快速定制的功能,参考了一些开源项目的配置文件和流程控制文件,这些大都是基于yml文件和json文件去实现的,因此决定通过json+sql来实现可定制的功能

可定制的json文件

目前json文件设想如下:

{
    "fileName":"文件名称",
    "titleTemplate" : [  //之所以用数组的形式是为了可以日后扩展为一个文件中多个sheet页
        {
            "sheetName" : "sheet页名称",
            "title":
            [
                {
                    "titleName": "表头的标题",
                    "headName": "与后续内容数据对应的一个key",
                    "heightSize": 单元格宽度
                }
            ]
        }
    ],
    "contentTemplate": [ //同样采用数组的方式是为了保证每个sheet都有对应的sql
        [
            {
                "execute":"select distinct street as street from epidemic_house",  //待执行的sql
                "args":"street",       //需要去传递的参数作为下个分组使用
                "split": true
            },
            {
                "execute":"select * from epidemic_house where street = ${street}" //需要导出文件用的sql,参数为上个sql传递过来的,根据上个sql执行结果分批执行,待生成文件sql无args参数(目前仅仅支持一个参数)
            }
        ]
    ]
}

json文件中的titleTemplate是为了生成导出excel中的标题信息,contentTemplate是通过sql去查询需要的数据,最后通过java代码去完成excel的拼接(目前只支持一个sheet页的处理,不支持多个sheet页的处理)

一个简单的样例

该案例是为了完成对待处理数据的超大规模分组,根据street参数生成每个street为分组的excel数据

{
    "fileName":"20221124高风险地区分类",
    "titleTemplate" : [
        {
            "sheetName" : "poiScript测试",
            "title":
            [
                {
                    "titleName": "街道",
                    "headName": "street",
                    "heightSize":3000
                },
                {
                    "titleName": "社区",
                    "headName": "village",
                    "heightSize":4000
                },
                {
                    "titleName": "具体地区",
                    "headName": "location",
                    "heightSize":4500
                },
                {
                    "titleName": "时间",
                    "headName": "time",
                    "heightSize":3000
                }
            ]
        }
    ],
    "contentTemplate": [
        [
            {
                "execute":"select distinct street as street from epidemic_house",
                "args":"street",
                "split": true
            },
            {
                "execute":"select * from epidemic_house where street = ${street}"
            }
        ]
    ]
}

代码部分

代码部分并无特别惊艳之处,只是实现了两个最主要的功能

  • 1、实现对超大规模数据拆分并生成多个excel
  • 2、实现通过sql的迭代查询从而完成超大规模数据的分组导出
    代码一:实现对超大规模数据拆分并生成多个excel
    /**
     * 提前判断内容的数据连是否过大excel是否装得下,是否需要分成多个excel文件
     * @param sheetName
     * @param titleData
     * @param contentData
     * @param fileName
     */
    private void preCreateExcelFile(String sheetName, JSONArray titleData, JSONArray contentData, String fileName) {

        if(contentData.size() < EXCEL_ROE_LIMIT + 1)  {
            createExcelFile(sheetName, titleData, contentData, fileName);
        } else {
            int totalCount = contentData.size()/EXCEL_ROE_LIMIT + 1;
            for(int i=1;i<= totalCount; i++) {
                int fromIndex = (i-1)*EXCEL_ROE_LIMIT;
                JSONArray subContentData = new JSONArray();
                for(int j = fromIndex; j<((fromIndex+ + EXCEL_ROE_LIMIT)>contentData.size()?contentData.size():(fromIndex+ + EXCEL_ROE_LIMIT)); j++) {
                    subContentData.add(contentData.getJSONObject(j));
                }
                createExcelFile(sheetName, titleData, subContentData, fileName + "part" + i);
                subContentData.clear();
            }
        }
    }

代码二:实现通过sql的迭代查询从而完成超大规模数据的分组导出

/**
     * 开始进行分文件处理
     * @param contentData 内容信息
     * @param titleData 标题信息
     */
    private void createSplitExcelByFile(JSONArray contentData, JSONObject titleData, String fileName) {
        String args = "";
        JSONArray titleName = titleData.getJSONArray("title");
        List<Map<String, Object>> tempExecMap = Lists.newArrayList();
        for(int i=0;i<contentData.size();i++) {
            JSONObject contentJSON = contentData.getJSONObject(i);
            String execute = contentJSON.getString(EXECUTE);
            if(!StringUtils.isEmpty(args)) {
                //当前待执行的sql是最终生成文件的sql,执行处理
                if(CollectionUtils.isEmpty(tempExecMap)) {
                    //如果不需要根据参数进行拆分的话,直接导出
                    createExcelFile(titleData.getString(SHEET_NAME), titleName,  executeOrder(execute, titleName), fileName);
                } else {
                    //需要分组,根据之前查询的分组结果进行拆分
                    for(int j=0;j<tempExecMap.size();j++) {
                        execute = execute.replaceAll("\\$\\{" + args + "\\}", "\"" + tempExecMap.get(j).get(args).toString() + "\"");
                        preCreateExcelFile(titleData.getString(SHEET_NAME), titleName,  executeOrder(execute, titleName), fileName+tempExecMap.get(j).get(args));
                        execute = contentJSON.getString(EXECUTE);
                    }
                }
            } else {
                //有参数,表示当前待处理的sql并不是最终生成文件的sql,作为前置查询条件继续执行
                tempExecMap = poiScriptService.executeOrder(execute);
                args = contentJSON.getString(ARGS);

            }
        }
    }

样例json执行结果

这些excel根据超大规模分组实现的,共分类为五百个excel,每个excel数据量上万,截图仅展示一小部分

在这里插入图片描述

详细的代码链接请看:https://github.com/rootdeng77/rootdeng.github.io/tree/master/src/main/java/com/example/rootdeng/POIScript

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值