Excel VBA重复更改控制单元hogs内存

时间:2014-08-03 12:17:54

标签: excel vba excel-vba memory

我在网上搜索得非常广泛,但没有找到任何类似的经历。有什么想法吗?

我在VBA中有一个简单的子程序来更改控制单元。该控制单元由另一张表中的公式使用。随着代码更改控件值,Excel使用越来越多的内存达到了excel停止的程度。

基本上我有一个包含3000行和330列的工作表设置。在工作表的每个单元格中填充以下相同的公式:

=sum(sheet1!F8:INDEX(sheet1!F8:F$3000,Control!$D$1))

因此,在单元格A1中,您将获得上面的公式,并在单元格中说B1,您将拥有:

=sum(sheet1!F**9**:INDEX(sheet1!F9:F$3000,Control!$D$1))

代码更改的控件值为Control!$D$1,因此将控件从2更改为4将导致计算sheet1中2到4个连续行的运行总和。 请注意,代码首先在控制单元(200)中设置一个较高的值,然后向下运行2.因此,内存使用量的增加实在令我感到困惑。

我的代码是:

For i = 200 To 1 Step -1
    Application.Calculation = xlCalculationManual
    ClearClipboard 'sets cutcopymode to false
    Range("Control!d1").Value = i
    Application.Calculation = xlCalculationAutomatic
Next i

最后,我尝试了以下替代方案,但没有一个适合我:

  • 在VBA阵列中进行所有计算:由于VBA不是多线程的,因此速度非常缓慢(重点是利用excel工作表中的公式来利用我的cpu核心)。
  • 设置screenupdating = false,enablevents = false,cutcopymode = false 没有显着改进
  • 将公式转换为值并通过VBA重新输入公式:再次减慢计算速度
  • 手动减少处理器数量:因为我需要快速计算,否则无法实现方法的目的

这是一个excel bug吗?

1 个答案:

答案 0 :(得分:0)

我对你的问题进行了更多的研究。构建运行和函数的方式必须创建许多中间范围:

=sum(sheet1!F8:INDEX(sheet1!F8:F$3000,Control!$D$1))

首先,sheet1!F8:F$3000,第二个是INDEX()函数的结果,第三个是SUM()的参数。 相反,我建议只使用OFFSET()函数构造一个范围(最小值)。它适合于任务,因为控制参数是标量,OFFSET()从范围和标量创建新范围。 然后运行总和是

=SUM(OFFSET(sheet1!$A$1;ROW()-1;COLUMN()-1;Control!$D$1;1))

其中控制值仅设置要求和的范围的大小。在我使用2000 x 14单元和200个循环的测试中,没有观察到的内存消耗增加。由于这两种方法(INDEX()和OFFSET())对于一张大小非常快,我不能对计算时间作任何假设(但请参见下面的提示)。

我添加了ROW()和COLUMN()函数以使公式自我调整 - 总和的起始地址将是公式所在单元格的相同地址。这样,表格中的所有公式完全相同,不必根据其位置进行更改。

关于运行时,我建议你不要将计算模式改为循环(即自动)。我注意到每次更改模式都会产生几秒钟的巨大开销。更改控制单元后,必须计算一次所有相关单元,并将模式设置为手动不会改变它。

最后,如果您使用原始数据尝试此公式,请测试是否遗漏ClearClipboard命令会产生任何影响。最终它将不得不调用Windows功能,从而离开Excel处理环境,除了美容用途之外,我无法理解为什么它在这里需要。