本帖最后由 happym8888 于 2012-1-12 10:19 编辑
编写高效Excel VBA代码的最佳实践(三)
http://www.excelpx.com/thread-219335-1-1.html
编写高效Excel VBA代码的最佳实践(四)
下面的示例代码更简洁,其运行速度大约是最佳实践(三)中结尾处代码的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 注:您也能通过使用对象变量在循环外部调用该对象。 |