楼主 wise |
VBA优化代码学习 一、强制声明变量 VBA并没有要求用户必须声明每个变量,VBA会自动为每个变量分配数据类型。这是VBA程序的一个兼容性的优点。但如果不声明变量,其类型程序在执行时就会消耗更多的内存,相当于消耗效率来换取兼容性。 如果需要提升程序效率,在编写代码的时候,应尽量将所有变量显示声明。
- Sub a()
- Dim i As Integer '声明变量类型
- Dim j '没有声明变量
- i = 100
- j = 3000
- MsgBox i & "*" & j & "=" & i * j
- End Sub
|
2楼 wise |
二、善用常量 如果某个数值或字符在程序中反复出现,则尽量声明一个产量来取代该值,在后面代码使用中直接调用常量。 具体看下例:
- Const Pi = 3.141526
- Sub 常量()
- MsgBox "圆的面积为:" & Pi * 2 ^ 2
- End Sub
三、关闭屏幕更新 在单元格中写入数据或批量插入对象时,每执行一句代码屏幕会更新一次,而更新屏幕需要时间。在大多数情况下,完全没有必要更新屏幕状态。开发者可以关闭屏幕更新来提升效率,等待所有过程执行完毕后再恢复屏幕更新即可。 控制屏幕更新开、关的属性是: Application.ScreenUpdating=True/False 例子1:
- Sub 隐藏偶数列()
- Dim col As Long, Tim As Long
- Tim = Timer
- For col = 1 To Columns.Count
- If col Mod 2 = 0 Then
- Cells(1, col).EntireColumn.Hidden = True
- End If
- Next
- MsgBox "程序运行了" & Format(Timer - Tim, "0.00") & "s"
- End Sub
在我的电脑上运行0.42S 例子2:
- Sub 隐藏偶数列一()
- Dim col As Long, Tim As Long
- Application.ScreenUpdating = False
- Tim = Timer
- For col = 1 To Columns.Count
- If col Mod 2 = 0 Then
- Cells(1, col).EntireColumn.Hidden = True
- End If
- Next
- Application.ScreenUpdating = True
- MsgBox "程序运行了" & Format(Timer - Tim, "0.00") & "s"
- End Sub
而该例子在我电脑的03版上面,运行才0.00s,效率提高了很多倍。 注意:Application.ScreenUpdating = False 这句代码通常放置在循环语句之前,在循环完成后再恢复屏幕更新,否则会影响正常工作。 |
3楼 wise |
四、利用With 减少对象读取次数 例子1:
- Sub Macro1()
- Range("I3").Font.Bold = True
- Range("I3").Font.Italic = True
- Range("I3").Font.Underline = xlUnderlineStyleSingle
- Range("I3").Font.ColorIndex = 5
- End Sub
例子2:利用with 来优化
- Sub Macro1()
- With Range("I3").Font
- .Bold = True
- .Font.Italic = True
- .Font.Underline = xlUnderlineStyleSingle
- .Font.ColorIndex = 5
- End With
- End Sub
单独执行以上两段代码,执行效率差别不大,但如果存在多段代码,累积起来对程序的效率就会有较大的影响了。 |
4楼 罗刚君 |
|
5楼 wise |
五、利用变量来减少对象读取次数 如果一个变量在一个过程中多次出现,应考虑用一个变量来替换对象。因为变量存于内存中,VBA读取内存数据远远快于对象。 如例子1:
- Sub a()
- Dim T As Long, rng As Range
- T = Timer
- For Each rng In Range("A1:A2000")
- If rng > [B1] Then rng.Interior.ColorIndex = 5
- Next
- [C1] = Format(Timer - T, "0.00") & "S"
- End Sub
在代码中,单元格B1 给引用了2000次,程序执行在我的电脑上是1.38S 例子2:
- Sub b()
- Dim T As Long, rng As Range, st As Long
- T = Timer
- st = [B1]
- For Each rng In Range("A1:A2000")
- If rng > st Then rng.Interior.ColorIndex = 5
- Next
- [C2] = Format(Timer - T, "0.00") & "S"
- End Sub
在例子2代码中,单元格B1仅需要读取一次。在后面的循环中,单元格B1不再参与运算,而是在内存中的变量“标准”在参与运算。该运算速度是0.17S(我的电脑上)。 |
6楼 wise |
六、善用带$的字符串处理函数 在VBA中,有两套字符串处理函数,包含带"$"和不带"$"的函数,例如mid 和mid$,Left 和Left$,Right 和Right$。 如果不使用带"$"符号的函数计算字符串,那么VBA将字符串作为变体数据来进行计算,而使用带"$"的函数时,则将字符串当作string类型来进行计算,显示变体型数据在计算时需要更多的内存空间。 如下面两段代码:
- Str=mid("Wise",2)
- Str=mid$("Wise",2)
第二句在执行效率上会占优势。 |
7楼 wise |
六、善用带$的字符串处理函数 在VBA中,有两套字符串处理函数,包含带"$"和不带"$"的函数,例如mid 和mid$,Left 和Left$,Right 和Right$。 如果不使用带"$"符号的函数计算字符串,那么VBA将字符串作为变体数据来进行计算,而使用带"$"的函数时,则将字符串当作string类型来进行计算,显示变体型数据在计算时需要更多的内存空间。 如下面两段代码:
- Str=mid("Wise",2)
- Str=mid$("Wise",2)
第二句在执行效率上会占优势。 |
8楼 wise |
七、循环中减少步长来提速 当使用有针对性的For循环,即仅仅需要对循环对象中的部分对象进行操作时,应该调整循环的步长来减少循环的次数。 对比下面两个例子: 例子一:
- Sub T1()
- tim = Timer
- For i = 1 To 10000
- If i Mod 2 = 1 Then Cells(i, 1).EntireRow.Interior.ColorIndex = 23
- Next i
- MsgBox Format(Timer - tim, "0.00") & "s"
- End Sub
该代码要循环次数是10000次 例子二:
- Sub T2()
- tim = Timer
- For i = 1 To 10000 Step 2
- Cells(i, 1).EntireRow.Interior.ColorIndex = 23
- Next i
- MsgBox Format(Timer - tim, "0.00") & "s"
- End Sub
而例子二循环的次数是5000次。 实现同样的代码,但却循环的次数有差异,明显是代码二比代码一效率更高。 |
9楼 wise |
八、利用数组代替单元格对象 VBA处理数组的速度远快于对象的速度,对于可以利用数组来替换对象都尽量使用数组。 以下两个例子来对比速度: 例子1:
- Sub 不及格()
- Dim i As Integer, tim As Long
- tim = Timer
- For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
- If Cells(i, 2) < 60 Then Cells(i, 3) = "不及格"
- Next i
- MsgBox Format(Timer - tim, "0.00") & "秒"
- End Sub
例子2:
- Sub b()
- Dim i As Long, tim As Long, arr1(), arr2()
- tim = Timer
- arr1 = Range([B2], Cells(Rows.Count, 2).End(xlUp))
- ReDim arr2(1 To UBound(arr1), 1 To 1)
- For i = 1 To UBound(arr1)
- If arr1(i, 1) < 60 Then arr2(i, 1) = "不及格"
- Next i
- Range([c2], Cells(Rows.Count, 2).End(xlUp).Offset(0, 1)) = arr2
- MsgBox Format(Timer - tim, "0.00") & "秒"
- End Sub
一样的效果,但明显例子2的速度要比例子1的速度要快! |
10楼 wangqilong1980 |
脚踏实地,慢慢往前爬 |
11楼 ANDY0393 |
谢谢lz分享,这些很实用,学习了 |