如何在Excel 2003中加速我的宏?


0

我有一个宏,将数据从一个单元格复制到另一个单元格并使用 VLOOKUP 除其他外,公式。我的电子表格包含近2000行。

当我在Excel 2003中运行它时,Excel开始减速,因为宏处理行500及以上。当它到达第1000行时会变得更糟。完成需要5个多小时。

但是,在Excel 2007中,宏只运行了半个小时。

谁能帮我找到一个好的解决方案?


5
我们必须看到你的代码
datatoo

除了下面有用且信息丰富的答案之外,您是否在循环中明确选择单元格或范围?这是一个很大的表现,不是没有,尝试只使用带有变量的Range对象......
Our Man in Bananas

你考虑过将表格数据复制到数组并在内存中处理吗?
Our Man in Bananas

Answers:


2

tumchaaditya建议的博客提供了一些值得实施的优秀建议,但我怀疑他们会在这方面提供帮助。

对我来说,关键问题是宏放慢了速度。你有这样的命令:

StrA = StrA & NewData

ReDim Preserve MyArray(1 To UBound(MyArray)+1)

这些命令使StrA和MyArray略大。对于每个循环,解释器必须为较大的对象找到空间,从旧对象复制数据,然后释放旧对象以进行垃圾收集。每当你使StrA或MyArray变大一点时,这个过程需要更长的时间。我不知道Excel 2003为什么问题更严重;也许Excel 2007有一个更好的垃圾收集器。

如果要从每行累积数据,这样的事情要好得多:

Option Explicit
Type SRowDtl      ' The definition of a User Type must preceed any routines
  Info1 As String
  Info2 As Long
  Info3() As Double
End Type

Sub ProcessRows()

  Dim RowDtl() as SRowDtl
  Dim InxRowDtlCrntMax as Long 

  ReDim RowDtl(NumberOfRows)
  InxRowDtlCrntMax = -1 

  For Each Row ....

     ' Store data from new row
     InxRowDtlCrntMax = InxRowDtlCrntMax+1

     RowDtl(InxRowDtlCrntMax).Info1 = xxx
     RowDtl(InxRowDtlCrntMax).Info2 = yyy
     RowDtl(InxRowDtlCrntMax).Info3(5) = zzz

  Next

如果您不熟悉大多数语言称为Structures和VBA调用用户类型的内容,则语法可能看起来很奇怪。但是,一旦您对语法感到满意,结构就会使您的代码更清晰,而且通常更快。


甚至可能值得将工作表数据复制到数组然后在内存中处理它
Our Man in Bananas

@Philip。我同意从工作表到数组的单个加载速度更快但我决定在没有看到原始代码的情况下,可以/应该引入多少新技术的限制。 tumchaaditya提供的链接详细介绍了很多很好的技术,但我认为真正的问题可能是垃圾收集,并且仅限于此问题。如果OP没有任何回应,我不愿意进一步处理此事。
Tony Dallimore

2

在查看代码之前,我无法确切地确定原因。但是现在,请看以下链接: Office.Com - Excel VBA性能编码最佳实践
Ozgrid.com VBA加速VBA代码

他们描述了如何优化任何excel宏的性能。

  1. 加速代码并停止屏幕闪烁

    Application.ScreenUpdating=False
    Application.ScreenUpdating=True
    
  2. 执行代码时防止计算

    Application.Calculation = xlCalculationManual
    Application.Calculation = xlCalculationAutomatic
    
  3. 如果您有工作表或工作簿事件,请加速代码。

    还会阻止事件中的无限循环

    Application.EnableEvents = False
    Application.EnableEvents = True
    
  4. 使用对象时使用With语句

    With Range("A1")
        .Font.Bold = True
        .Interior.ColorIndex = 6
    End With
    
  5. 使用VbNullString而不是=“”当需要将String变量默认为默认值“”时

    strWords = "Cats"
    strWords = vbNullString
    
  6. 将相对公式插入一系列单元格:比自动填充或复制更快

    Range("A1:A200").FormulaR1C1 = "=SUM(RC[1]:RC[5])"
    
  7. 尽可能避免使用复制和粘贴(绕过剪贴板)

    Sheet1.Range("A1:A200").Copy Destination:=Sheet2.Range("B1")
    
  8. 始终正确声明您的变量!

    Dim wSheet as Worksheet
    Set wSheet = Sheet1
    Set wSheet = Nothing
    

1
您应该在答案中总结这些链接,以避免链接腐烂。
JimmyPena

我添加了一个摘要
nixda
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.