本帖最后由 Clark.Pan 于 2023-12-22 18:06 编辑
背景:
用户需要对Excel文档逐行进行处理,逐行的进行单元格合并以及一些其他设置。在这时候会发现通过循环逐行操作,性能效率非常低下。
解决方案:
首先定位这个问题是跟单元格合并有关系,GcExcel在单元格合并的底层算法会检测合并区域的属性设置,并排除合并后可能出现的冲突,这个检测就是导致性能低下的原因。
接下来,我们做几个小实验:setLineStyle
如下面代码所示,循环对一个1000行15列的单元格进行合并设置,并在循环中对单元格设置边框。值得注意的是为了模拟最坏情况出合并冲突,我在setLineStyle的设置范围上故意写成了1行,这样每两行进行合并时会产生样式设置的冲突。
- for(int i = 0; i < 1000; i++) {
- for(int j = 0; j < 15; j++) {
- worksheet.getRange(i*2,j,1,1).getBorders().get(BordersIndex.EdgeTop).setLineStyle(BorderLineStyle.Medium);
- worksheet.getRange(i*2,j,1,1).getBorders().get(BordersIndex.EdgeTop).setColor(Color.GetGreen());
- worksheet.getRange(i*2,j,2,1).merge();
- }
- }
复制代码
运行在个人PC上测试,结果居然花费了33058 ms。这是一个不能令人接受的数字。
接下来我们换一个试验,还是上述代码,将merge的位置与上面边框设置的位置对调
- for(int i = 0; i < 1000; i++) {
- for(int j = 0; j < 15; j++) {
- worksheet.getRange(i*2,j,2,1).merge();
- worksheet.getRange(i*2,j,1,1).getBorders().get(BordersIndex.EdgeTop).setLineStyle(BorderLineStyle.Medium);
- worksheet.getRange(i*2,j,1,1).getBorders().get(BordersIndex.EdgeTop).setColor(Color.GetGreen());
- }
- }
复制代码 然后我们重新跑一下结果,25105 ms 。快了几乎四分之一,虽然时间上还是无法让人接受,从实验可以看出GcExcel内部存在一些策略,根据设置执行顺序的不同会有着不同的性能体验。
接下来,我们将merge与颜色设置拆开执行,分别运行在两个循环中,如下面代码所示
- for(int i = 0; i < 1000; i++) {
- for(int j = 0; j < 15; j++) {
- worksheet.getRange(i*2,j,1,1).getBorders().get(BordersIndex.EdgeTop).setLineStyle(BorderLineStyle.Medium);
- worksheet.getRange(i*2,j,1,1).getBorders().get(BordersIndex.EdgeTop).setColor(Color.GetGreen());
- }
- }
-
- for(int i = 0; i < 1000; i++) {
- for(int j = 0; j < 15; j++) {
- worksheet.getRange(i*2,j,2,1).merge();
- }
- }
复制代码
代码中,merge在设置边框之后进行,我这边测试的结果是 15404ms,又快了超过三分之一,但这还不够。
我们再次修改代码,将循环merge和循环边框设置的位置交换:
- for(int i = 0; i < 1000; i++) {
- for(int j = 0; j < 15; j++) {
- worksheet.getRange(i*2,j,2,1).merge();
- }
- }
- for(int i = 0; i < 1000; i++) {
- for(int j = 0; j < 15; j++) {
- worksheet.getRange(i*2,j,1,1).getBorders().get(BordersIndex.EdgeTop).setLineStyle(BorderLineStyle.Medium);
- worksheet.getRange(i*2,j,1,1).getBorders().get(BordersIndex.EdgeTop).setColor(Color.GetGreen());
- }
- }
复制代码
运行一下结果,得到一个惊人的数据:2378ms,这次终于体现出了GcExcel的性能。
有兴趣的小伙伴可以自行测试上述代码,结果可能会跟各自机器配置不同而有差异,但是对比的效果一定是可以明显看出来的。
综上所述在有合并处理的时候应当优先处理合并行为,另外对于初次使用的用户,可能没有这些知识背景,使用时可能会写出一些有性能问题的Case。这个时候可以联系我们的技术顾问,提供相应的信息,他们有义务为您进行排查。
|
|