使用For Each…Next循环 可以使用For Each…Next循环来保证程序代码更快地执行。在使用For Each…Next循环时,对于存储在集合或数组中的每个对象执行一组语句,程序更简洁,也更容易阅读、调试和维护。当For Each…Next语句迭代集合时,自动指定一个对集合当前成员的引用,然后在到达集合的尾部时跳出循环语句。 与使用计数进行循环相比,在遍历集合或数组时使用For Each…Next循环将更快。在多数情况下,使用For Each…Next循环也更方便,并且使您的宏更简洁、更容易阅读和调试。 下面的示例运行很慢,因为在每次循环重复时它设置并调用了行变量.Row(i)。 Sub DoSomethingSlow() Dim Start As Double, Finish As Double Start = Timer ''-------------------------------------- Dim Cell As Range, i As Long With Sheet1.Range(''A1:A10000'') For i = 1 To 10000 Set Cell = .Rows(i) If Cell > 0 Then Cell.Font.ColorIndex = 5 End If Next End With ''-------------------------------------- Finish = Timer MsgBox ''本次运行的时间是'' & Finish - Start End Sub 下面的示例代码更简洁,其运行速度大约是上面代码的2~3倍。因为For Each…Next循环自动记录行数并定位,而不需要调用变量i。 Sub DoSomethingFaster() ''快两至三倍 Dim Start As Double, Finish As Double Start = Timer ''-------------------------------------- Dim Cell As Range With Sheet1 For Each Cell In .Range(''A1:A10000'') If Cell > 0 Then Cell.Font.ColorIndex = 5 End If Next End With ''-------------------------------------- Finish = Timer MsgBox ''本次运行的时间是'' & Finish - Start End Sub 在执行循环时考虑如何能够尽可能地节省资源 (1)分析循环以查看是否正在不必要地执行一些消耗内存的重复操作。例如,是否可以在循环外(而不是在循环中)设置某些变量?每次都通过循环执行的转换过程是否可以在循环之外执行? (2)考虑是否必须在满足特定的条件时才执行循环。如果是,也许可以更早地退出循环。例如,假设正在对一个不应该包含数字字符的字符串进行数据验证。如果循环要检查字符串中的每个字符以确定其中是否包含数字字符,那么您可以在找到第一个数字字符时立即退出循环。 (3)如果必须在循环中引用数组的元素,可以创建一个临时变量存储该元素的值,而不是引用数组中的值。从数组中检索值比从相同类型的变量读取值要慢。 (4) 将属性和方法放在循环外部 在代码运行时,获取变量的值快于获取属性的值。因此,如果您的代码在循环内部获取属性的值,您可以在循环外部将该属性的值先指定给一个变量,然后在循环内部使用此变量代替属性的值,这样的代码将运行得更快。 下面所示的代码运行较慢,因为在每次重复循环时都必须获取Sheet的Range属性的值。 Sub TryThisSlow() Dim Start As Double, Finish As Double Start = Timer ''-------------------------------------- Dim MyLoop As Long For MyLoop = 2 To 4001 Cells(MyLoop, 2) = Sheet1.Range(''B1'') Next ''-------------------------------------- Finish = Timer MsgBox ''本次运行的时间是'' & Finish - Start End Sub 下面的示例与上面所产生的结果相同,但比上面的要更快,因为在循环开始以前我们已经将Sheet的Range属性的值指定给了单独的变量MyVar。这样,代码将在每次重复循环时利用该变量的值,而不必每次都要调有属性。 Sub TryThisFaster() ''快约35%以上 Dim Start As Double, Finish As Double Start = Timer ''-------------------------------------- Dim MyVar As String, MyLoop As Long MyVar = Sheet1.Range(''B1'') For MyLoop = 2 To 4001 Cells(MyLoop, 2) = MyVar Next ''-------------------------------------- Finish = Timer MsgBox ''本次运行的时间是'' & Finish - Start End Sub 如果您在一个循环内部使用多个对象访问,您也可以使用With…End With将您能够移动的对象移到循环外部。下面的示例在每次循环重复时都调用Sheets对象和Cells属性。 Sub NowTryThisSlow() Dim Start As Double, Finish As Double Start = Timer ''-------------------------------------- Dim c As Long For c = 1 To 8000 Sheet1.Cells(c, 5) = c Next ''-------------------------------------- Finish = Timer MsgBox ''本次运行的时间是'' & Finish - Start End Sub 对上面的代码改写如下,使用With语句将调用Sheets对象移到循环外部,只剩余调用Cells。 Sub NowTryThisFaster() ''约快3倍 Dim Start As Double, Finish As Double Start = Timer ''-------------------------------------- Dim c As Long With Sheet1 For c = 1 To 8000 .Cells(c, 5) = c Next End With ''-------------------------------------- Finish = Timer MsgBox ''本次运行时间为'' & Finish - Start End Sub 注:您也能通过使用对象变量在循环外部调用该对象。 关于带有特定目的的VBA方法的更多的信息,您可参见VBA帮助系统相关主题。 结语 当然,代码优化可能不是绝对必要的,这依赖于您要做的工作……如果您正好编写了一个快速且简短的或者是一次性使用且与速度和/或简洁要求无关的代码,您就不需要优化代码。 但另一方面,如果您处理一个带有很多数据、工作簿、工作表等大的工程,再次检查您第一次编写好的代码,看看是否您的代码需要优化,而这样做总是值得的。 最终,您将养成编写代码的好习惯,将会使您的代码更简洁、运行更快速、并且容易为您自已和他人阅读和调试。同时,由于您的代码简洁,因而输入更快,工作效率更高。 |
|