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

news2025/7/9 17:45:55

基于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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/39225.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

诊断数据库ODX—数据库框架(基于ISO22901详解)

文章目录 前言一、ODX数据库自身架构是什么&#xff1f;二、ODX数据库架构具体组成部分和含义总结前言 车载诊断现阶段应用的诊断数据库大体分为三种&#xff1a; CDD&#xff08;Vector私有格式&#xff09;&#xff1b; ODX全球通用诊断数据库格式&#xff1b; DEXT&…

【零基础入门SpringMVC】第四期——RESTFUL专题

一、RESTFul 概述 1、什么是 RESTFul&#xff1f; REST 全称 Representational State Transfer 代表 表现层资源状态转移 视图层 控制层 表现层 百度百科这样说&#xff1a; RESTFUL是一种网络应用程序的设计风格和开发方式&#xff0c;基于HTTP&#xff0c;可以使用XML格式…

轻松应对80% 的工作场景?GitHub 爆赞的 Java 高并发与集合框架,面试官也拿我没辙

在工作中&#xff0c;笔者经常和掌握不同技术的朋友讨论具体问题的解决方案&#xff0c;发现在 Java 体系中&#xff0c;大家使用最多的是 Java 集合框架&#xff08;JCF&#xff09;和 Java 并发工具包&#xff08;JUC&#xff09;。实际上&#xff0c;JCF 和 JUC 已经能够覆盖…

Flutter高仿微信-第50篇-群聊-查看群成员

Flutter高仿微信系列共59篇&#xff0c;从Flutter客户端、Kotlin客户端、Web服务器、数据库表结构、Xmpp即时通讯服务器、视频通话服务器、腾讯云服务器全面讲解。 详情请查看 效果图&#xff1a; 实现代码&#xff1a; import package:flutter/material.dart; import package:…

Node.js 入门教程 7 从命令行运行 Node.js 脚本 8 如何退出 Node.js 程序

Node.js 入门教程 Node.js官方入门教程 Node.js中文网 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录Node.js 入门教程7 从命令行运行 Node.js 脚本8 如何退出 Node.js 程序7 从命令行运行 Node.js 脚本 运行 Node.js 程序的常用方法是&#…

【点云处理】点云法向量估计及其加速(5)

在上一篇文章【点云处理】点云法向量估计及其加速(4)中我们尝试对pcl自带的KDTree的k近邻搜索过程使用OpenMP加速&#xff0c;效果比较明显&#xff0c;有将近1倍的提速。在这篇文章中我们暂时放弃pcl自带的KDTree&#xff0c;转而使用另一大杀器nanflann库提供的KDTree。nanof…

玩链子游戏

一 游戏描述 有一条链子&#xff0c;上面有 n 颗钻石&#xff0c;钻石编号为 1&#xff5e;n 。可以对该链子执行两种操作&#xff1a; ① CUT a b c &#xff08;区间切割操作&#xff09; 切下从第 a 颗钻石到第 b 颗钻石的链子&#xff0c;把它插在剩余链子的第 c 颗钻石…

【食品加工技术】第五章 烘烤食品加工技术 笔记

【食品加工技术】第五章 烘烤食品加工技术 笔记5.1 焙烤食品概述烘烤食品的分类按发酵和膨化程度分类安装生产工艺分类烘烤食品的原料面粉糖蛋品乳及乳制品膨松剂烘烤设备常用设备恒温设备常用工具5.2 面包加工工艺和关键技术面包的分类面包的发酵原理面包的工艺流程一次发酵二…

uboot引导应用程序

uboot默认是支持执行应用程序的&#xff0c;就像引导内核一样&#xff0c;我们也可以自己写一个应用程序&#xff0c;让uboot启动时引导。 在uboot examples/standalone 目录下&#xff0c;有hello_world.c文件&#xff0c;编译uboot的时候&#xff0c;会自动编译hello_world.…

详解 InnoDB Cluster 主机名问题

详解 InnoDB Cluster 主机名问题 文章目录详解 InnoDB Cluster 主机名问题导言测试过程结论导言 因在写 【InnoDB Cluster】修改已有集群实例名称及成员实例选项 时发现主机名这块有一些问题&#xff0c;在其中进行了部分测试&#xff0c;但为使其内容精简&#xff0c;故将此部…

程序员必知的三款在线绘图工具

文章目录2.draw.io3.Lucidchart4.PrcessOn5.小结正所谓“一图胜千言”&#xff0c;无论是商务办公、PPT 演示、学习总结、技术交流、项目开发&#xff0c;我们常常都需要制作一些图表、流程图、架构图来更直观地呈现内容以及归类整理知识点。 今天就来说下程序员们常用的三款在…

【矩阵论】正规方程——生成子空间

5.1 子空间 5.1.1. 定义 设 W⊂CnW\subset C^nW⊂Cn &#xff0c;即子空间对线性组合封闭 若(1)对∀α,β∈W&#xff0c;有αβ∈W(对加法封闭)(2)对∀α∈W,∀k∈C&#xff0c;有kα∈W(对数乘封闭)\begin{aligned} 若 &(1)对\forall \alpha,\beta\in W&#xff0c;有\…

秋招失利,拿到这份“Java 高分指南(25 专题)”,金三银四翻盘有望

面试造火箭&#xff0c;工作拧螺丝&#xff01;金九银十灰溜溜地落榜&#xff0c;备受打击。正当准备明年金三银四之际&#xff0c;意外喜提朋友赠送的这“Java 高分指南&#xff08;25 专题&#xff09;”&#xff1a;Elasticsearch、微服务、Linux、JavaOOP、集合/泛型、Mysq…

Flutter高仿微信-第57篇-添加好友

Flutter高仿微信系列共59篇&#xff0c;从Flutter客户端、Kotlin客户端、Web服务器、数据库表结构、Xmpp即时通讯服务器、视频通话服务器、腾讯云服务器全面讲解。 详情请查看 效果图&#xff1a; 实现代码&#xff1a; /*** Author : wangning* Email : maoning20080809163.c…

ThreadLocal

文章目录一、ThreadLocal是什么二、ThreadLocal作用三、ThreadLocal的设计结构早期:现在:四、ThreadLocal核心方法1. set方法2. get方法3. remove方法五、ThreadLocal内存泄漏六、使用场景七、参考资料前言&#xff1a; 再写博客时&#xff0c;遇到了如何处理保存用户的信息时出…

基于共享储能电站的工业用户 日前优化经济调度matlab程序(yalmip+cplex)(yalmip+gurobi)

基于共享储能电站的工业用户 日前优化经济调度matlab程序&#xff08;yalmipcplex&#xff09;&#xff08;yalmipgurobi&#xff09; 参考文献&#xff1a;基于共享储能电站的工业用户 日前优化经济调度 摘要: 文章提出一种基于共享储能电站的工业用户日前优化经济调度方法。…

nginx反向代理,负载均衡配置

文章目录一.nginx代理简介二.nginx配置简介三.nginx作为反向代理的配置四.nginx作为负载均衡的配置五.使用nginx代理的坑一.nginx代理简介 其实nginx作为代理有两种 正向代理: 隐藏客户端的信息;如科学上网 反向代理: 隐藏服务端的信息;如负载均衡 二.nginx配置…

11.26

目录 一.做题出错 1. 2.数组长度的一半 3.选择题 二.优先级队列(堆) 1.二叉树的顺序存储 1.1 存储方式 1.2下标关系 2.堆(heap) 2.1概念 2.2 操作-向下调整 三 建堆 四.优先级队列 1 概念 2 内部原理 3.操作-入队 offer() 4.操作-出队 五.计算糖果 一.做题出错…

docker如何下载国外镜像

目录背景解决方案1、创建阿里云镜像仓库2、使用https://labs.play-with-docker.com下载镜像3、将镜像上传到阿里云镜像仓库4、从阿里云镜像仓库中拉取镜像到我们linux系统中5、改变我们linux系统中拉取的镜像名称背景 今天在安装grafana和prometheus&#xff0c;但是在下载下面…

Java数据结构

目录 1、栈 2、队列 3、数组 4、链表 5、树 7、平衡二叉树 8、红黑树 1、栈 特点&#xff1a;先进后出&#xff0c;后进先出 数据进入栈模型的过程称为:压/进栈 数据离开栈模型的过程称为:弹/出栈 2、队列 特点&#xff1a;先进先出&#xff0c;后进后出 数据从后…