Excel列表 – 对象VBA性能错误?

我在使用列表对象(AKA Excel表格)的Excel应用程序中遇到问题。 我怀疑这可能是一个错误,但尽pipe我谷歌search我找不到任何参考。 我已经为我的应用程序开发了一个解决方法,但是我感兴趣的是如果任何人都可以提供任何洞察,为什么会发生这种情况。

注意:我在Windows Vista上使用Excel 2007。 设置如下:我有一个电子表格,其中保存的数据列表对象,VBA代码可以通过命令button启动; 此代码可能会对工作表上的任意数量的单元格进行多次编辑,因此在任何编辑之前,Excel的“计算”模式都设置为“手动”。

我遇到的问题是,如果当前活动的单元格在列表对象中,那么将计算模式设置为手动似乎没有任何效果。 所以,如果用户在同一个实例中碰巧有一个繁重的计算工作簿打开,那么VBA代码运行非常缓慢。 我实际上不得不拉我的申请,发现这是由活动单元格造成的; 我用这个场景的简单版本创build了一个新的工作簿,以确认我的应用程序没有某种forms的损坏。

我已经做了一些testing用例,下面是我发现的结果:

  1. 虽然看起来一般与计算有关,但当计算模式在“手动”和“自动”之间切换时,仍然存在时间差…

    • 手动= 7.64秒
    • 自动= 9.39秒

    手动模式比自动模式less了20%。 但我的期望是他们会差不多,考虑到即使在手动模式下,问题似乎也是开始计算。

  2. 比较,当活动单元格不在列表对象,并且结果是巨大地不同…

    • 手动= 0.14秒
    • 自动= 3.23秒

    现在,“手动”运行速度提高了50倍,“自动运行”显示计算时间不应超过3.2秒! 所以现在第一个testing看起来好像在手动模式下可能运行了两次计算,在自动模式下运行了近三次。

  3. 再次重复这个testing,这次是在没有任何单元格的计算公式的情况下,突然它似乎不是很糟糕,

    • 活动单元格是List Object&Calc手动= 0.17秒
    • 活动单元格是List Object&Calc是Automatic = 0.20秒
    • 活动单元格为空并且Calc是手动= 0.14秒
    • 活动单元格为空并且Calc自动= 0.18秒

    这个速度还是比较慢,但是现在只有10-20%,不会让人觉察。 但是这确实表明这个问题必须以某种方式与计算相关,否则就应该和第一次testing一样长。

如果有人想创build这些testing来自己看,设置如下:

  • 添加了List对象的新工作簿(不必链接到任何数据)
  • 加一些计算公式(我刚做'= 1 * 1'重复了3万次)
  • 写一个快速的VBA代码, (i)循环数百次单元格的简单编辑,(ii)并logging花费的时间
  • 然后在更改列表对象和空单元格之间的活动单元的同时运行代码

我会非常感兴趣的是,如果有人能够解释为什么Excel会以这种方式行事,并且是一个错误,或者是否有一些与List对象有关的function,这些function实际上有一些真正的用途?

谢谢,斯图尔特

这与你发现的“bug”无关,这是相当有趣和有趣的。

我只是想分享一下,避免计算延迟是一个很好的方法。 我有这样的结果,现在我一直在使用它。

简而言之,Excel需要很长时间在“VBA世界”和“电子表格世界”之间来回复制数据。

如果你一次完成所有的“读”,处理,然后一次完成所有的“写”,你会得到惊人的performance。 这是使用不同的数组完成的,如下所述:

http://msdn.microsoft.com/en-us/library/ff726673.aspx#xlFasterVBA

在标有“在单个操作中读取和写入大块数据”的部分中

我能够重构我花了5分钟运行的一些代码,并将其降低到1.5分钟。 重构花了我10分钟,这是惊人的,因为它是相当复杂的代码。

关于表格performance(一般而言):

我知道这是一个老问题,但我希望得到这个logging。

旧版本的Excel和2007之后版本之间的一个变化是,Excel现在激活了任何PasteSpecial操作的目标工作表。 您无法通过closuresScreenUpdating并手动进行计算来覆盖它。 这种激活会使表单可见,并导致无法控制的闪烁。

我的原始VBA代码在运行Excel 2000的旧式单处理器XP机器上运行速度非常快。在现代机器上对Excel 2013的更改在代码执行速度非常慢时非常令人惊叹。 杀死性能的三个方面是PasteSpecial从一个表单到另一个表单,以及需要激活表单(缩放级别,高级filter,表级范围名称等)以及自动执行表单保护/取消保护的任何其他代码。

这太糟糕了,因为PasteSpecial帮助“清理”你复制的数据(直接使用.Copy到目标将会引发偶尔的错误)。

因此,您需要检查您的代码,并确保您正在使用直接分配给您需要的数据types(例如Value,Value2,Text和Formula中的数据types)的正确属性,而不是PasteSpecial。

例如.Range(“MYRANGE”)。Value = .Cells(5,7).Value2

您还需要谨慎对待在整个代码中使用“select”和“激活”。

如上所述,您在Excel论坛中发现的关于最后一点的许多评论将使您“从不”需要使用Activation,这显然是不真实的,因为Excel中的一些内容仅适用于或需要活动工作表。 了解激活是通过特定的方法或使用对象自动强制的情况,也有助于编码。 不幸的是,你不会看到这方面的文件。

更新:

关于条件格式,在遇到大量有条件格式的单元格时,您会在各种论坛中发现很多关于Excel缓慢的抱怨。 我怀疑这会影响Excel表格,因为他们有很多表格格式选项。 为了testing这个,我把一个我们使用的大型工作簿,当前格式化为几个工作表,在他们上面使用相同样式的Excel表格。

将表格转换为常规范围之后,我注意到代码执行的速度没有任何区别 。 这似乎表明,Excel表格格式的使用远远优于有条件地格式化自己的单元格数组。