开发报表平台,需要有报表系统和用户的数据交互,报表又称之为线上的excel,所以在与系统交互的过程中,除了用户在线上直接录入数据,excel的导入导出是重要的一环.下面就说下我们在开发过程中对这块的处理。
poi
没错,不出意外的我们使用了poi作为我们处理excel的开发组件,poi对excel的操作提供了丰富的api,让我们可以对excel的每个单元格的样式,格式等都有很好的操作。但是poi十分吃服务器内存也是一个事实,到现在这个问题还是没有很好的优化。
读写模式

POI读取Excel有两种模式,一种是用户模式(可修改),一种是SAX事件驱动模式,将xlsx格式的文档转换成CSV格式后进行读取。用户模式API接口丰富,使用POI的API可以很容易读取Excel,但用户模式消耗的内存很大,当遇到很大sheet、大数据网格,假空行、公式等问题时,很容易导致内存溢出。POI官方推荐解决内存溢出的方式使用CVS格式解析,即SAX事件驱动模式。下面主要是讲解如何读取大批量数据:
导出大数据量的excel(07)
这个比较简单,我们只需要 用 SXXFWorkbook替换掉我们用的 XSSFWorkbook就可以了(POI3.8后),SXXFWorkbook 是poi为我们实现的一个 支持大数据量导出的WookBook实现类,它的整体实现就是,在新建的时候指定内存中容纳多少行数据,当持续写入的行数超过我们设置的数量的时候,就会刷新内存中的数据写入到硬盘中,内部实现还是 XSSFWorkbook这个类,所以我们在构建 SXXFWorkbook的时候1
2//我们需要指定一个内存中的行数,后台的操作就和 XSSFWorkbook一致了。
SXSSFWorkbook sxWorkbook = new SXSSFWorkbook(2000);
这样我们在写出大数据量的excel的时候,就不会在出现内存溢出问题了。(只能导出)
导入大数据量的excel(07)
如果是大数据量的导入,我们肯定不能用用户模式,用户模式是对所有的数据全部放到内存中,34M大小的07版本的excel用用户模式读取,需要大概4G的内存消耗,所以太消耗内存了,不过用户模式可以读,可以写。是最为方便的一种模式,如果导入大数据量的excle,推荐一个开源的项目xlsx-streamer,作者已经给我们写好了xml分批量读取excel的代码了,我们只要直接用就行了。1
2
3
4
Workbook wk = StreamingReader.builder().rowCacheSize(100) //缓存到内存中的行数,默认是10
.bufferSize(2048) //读取资源时,缓存到内存的字节大小,默认是1024
.open(excel);
不过这种方式是只能读取信息,并且不支持随机访问sheet页种的每行数据,我们获取数据需要使用迭代器的方式获取。作者实现的这个开源组件不支持获取sheet页中的合并单元格信息,但是我们项目中使用必须要合并单元格的信息来完成业务操作,并且我们项目中的大部分组件使用的poi是3.9的,作者用的poi是4.0.0 所以最后我只能在开源作者的基础上做了自己的定制,可以获取到sheet页的合并单元格信息,并且poi版本是3.9。如果你们项目也需要自己的定制,也需要在作者的基础上进行开发,源代码中作者用的是解析xml的形式来读取excel的,也比较好理解和修改,我自己修改的版本在这里