Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 377|回复: 0

JAVA导出上万行Excel数据的解决方案

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-1 14:44:50 | 显示全部楼层 |阅读模式

    在Java Web开发中,经常需要导出大量的数据到Excel,动辄就上千,上万行的数据让我们的程序感觉压力很大,甚至都出现无法导出的情况,使用POI、JXL直接生成Excel,很容易就造成内存溢出了。即使不溢出,由于代码执行耗时太久也会长时间阻塞web页面,导致web系统并发访问性能急剧下降。

     

    怎么解决内存溢出问题呢?用POI处理的话,毕竟数据还是一次性在内存中进行保存的,数据量太大JVM就内存溢出了,这时我们想是不是可以导出多个Excel呢?

     

    沿着这个思路去想问题,首先我们要确定数据量有多大,然后确定一个Excel导出多少条数据,这样就可以确定导出的Excel的数量,于是我们就可以循环的导出Excel并保存在任意的临时目录中去,这样如果内存不够的话虚拟机就会去进行回收已经保存的Excel在内存中的空间。

     

    假设我们我们已经成功的生成了多个Excel,这时我们怎么把这N个Excel文档传到客户端展示呢?其实一个一个的传也未尝不可,但是考虑那样对用户来说体验不够好,用户保存一个个文件到本地再打开,再一个一个浏览或者打印很是不方便。

     

    用生成多个文件发送到客户端的方案增加了开发难度,生成文件的速度也更慢了。如果换一种方式,绕过JVM的内存限制问题应该怎么解决呢?可以在客户端生成文件。

     

    网上能找到几家做在线编辑office文件的产品,有的提供了js调用Office的VBA接口的对象,采用在客户端打开文件时,用js通过VBA接口把数据填充到Excel单元格中去生成文件,这样就绕过了服务器上内存溢出的问题,减轻了服务器的压力,是不是可行呢?经测试,此方式生成几千行数据的Excel表格速度就比较慢了,一旦上万行数据,执行效率就会急速降低甚至程序死掉。更为可怕的是,怎么把后台代码查询的数据集的上万行数据传递给前台页面的js,编程更痛苦。没有更好的方法了吗?也不是。

     

    本人最近研究了一个国产的商业软件PageOffice,本质上也是在客户端生成Excel表格的,但是这个产品提供的是服务器端的编程对象,接口很简单,调用起来比js舒服多了,通过对这个产品提供的服务器端Excel操作对象编程,客户端就能在用户需要Excel表格的时候实时生成,也同时解决了文件的在线预览和打印问题。PageOffice肯定是对Excel的接口做过深度优化的,本人测试的结果,填充上万行数据也能瞬间完成,还支持赋值公式、单元格样式和文本样式的设置(由于本人开发的项目中无需处理这些,对于这些功能没做研究,所以无法做深入的描述),所以在此与大家分享一下,有兴趣可以去PageOffice的官网下载一个试用版测试。

     

     

    附本人测试PageOffice导出2万行Excel表格的代码:

     

    Workbook wb = new Workbook();

    Sheet sheet1 = wb.openSheet("Sheet1");

    Table table = sheet1.openTable("B1:F2");

    for(int i=0; i<20000;i++) {

                                table.getDataFields().get(0).setValue(String.valueOf(i));//B列

                                table.getDataFields().get(1).setValue("测试");//C列

                                table.getDataFields().get(2).setValue("测试");//D列

    table.getDataFields().get(3).setValue("测试");//E列

    table.getDataFields().get(4).setValue("测试");//F列

                                table.nextRow();

             }

    table.close()

     

             PageOfficeCtrl poCtrl1 = new PageOfficeCtrl(request);

             poCtrl1.setServerPage("poserver.do"); //此行必须

    poCtrl1.webOpen("doc/template.xlsx", OpenModeType.xlsSubmitForm, "");

             poCtrl1.setTagId("PageOfficeCtrl1"); //此行必须

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-4 07:53 , Processed in 0.061406 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表