ExcelTip.Net留存知识帖 ---【注:附件之前被网盘供应商清空后,现已修复-现已修复-现已修复为本地下载!】
现在位置:首页 > E文精选 > Excel VBA > VBA优化代码运行效率

VBA优化代码运行效率

作者:绿色风 分类: 时间:2022-08-17 浏览:147
楼主
wise
VBA优化代码学习
一、强制声明变量
VBA并没有要求用户必须声明每个变量,VBA会自动为每个变量分配数据类型。这是VBA程序的一个兼容性的优点。但如果不声明变量,其类型程序在执行时就会消耗更多的内存,相当于消耗效率来换取兼容性。
如果需要提升程序效率,在编写代码的时候,应尽量将所有变量显示声明。

  1. Sub a()
  2. Dim i As Integer '声明变量类型
  3. Dim j '没有声明变量
  4. i = 100
  5. j = 3000
  6. MsgBox i & "*" & j & "=" & i * j
  7. End Sub
2楼
wise
二、善用常量
如果某个数值或字符在程序中反复出现,则尽量声明一个产量来取代该值,在后面代码使用中直接调用常量。
具体看下例:
  1. Const Pi = 3.141526
  2. Sub 常量()
  3.   MsgBox "圆的面积为:" & Pi * 2 ^ 2
  4. End Sub

三、关闭屏幕更新
在单元格中写入数据或批量插入对象时,每执行一句代码屏幕会更新一次,而更新屏幕需要时间。在大多数情况下,完全没有必要更新屏幕状态。开发者可以关闭屏幕更新来提升效率,等待所有过程执行完毕后再恢复屏幕更新即可。
控制屏幕更新开、关的属性是:
Application.ScreenUpdating=True/False
例子1

  1. Sub 隐藏偶数列()
  2.   Dim col As Long, Tim As Long
  3.   Tim = Timer
  4.   For col = 1 To Columns.Count
  5.      If col Mod 2 = 0 Then
  6.        Cells(1, col).EntireColumn.Hidden = True
  7.      End If
  8.   Next
  9.   MsgBox "程序运行了" & Format(Timer - Tim, "0.00") & "s"
  10. End Sub
在我的电脑上运行0.42S
例子2

  1. Sub 隐藏偶数列一()
  2.   Dim col As Long, Tim As Long
  3.   Application.ScreenUpdating = False
  4.   Tim = Timer
  5.   For col = 1 To Columns.Count
  6.      If col Mod 2 = 0 Then
  7.        Cells(1, col).EntireColumn.Hidden = True
  8.      End If
  9.   Next
  10. Application.ScreenUpdating = True
  11.   MsgBox "程序运行了" & Format(Timer - Tim, "0.00") & "s"
  12. End Sub
而该例子在我电脑的03版上面,运行才0.00s,效率提高了很多倍。
注意:Application.ScreenUpdating = False 这句代码通常放置在循环语句之前,在循环完成后再恢复屏幕更新,否则会影响正常工作。
3楼
wise
四、利用With 减少对象读取次数
例子1

  1. Sub Macro1()
  2.     Range("I3").Font.Bold = True
  3.     Range("I3").Font.Italic = True
  4.     Range("I3").Font.Underline = xlUnderlineStyleSingle
  5.     Range("I3").Font.ColorIndex = 5
  6. End Sub
例子2:利用with 来优化

  1. Sub Macro1()
  2.   With Range("I3").Font
  3.    .Bold = True
  4.    .Font.Italic = True
  5.    .Font.Underline = xlUnderlineStyleSingle
  6.    .Font.ColorIndex = 5
  7.   End With
  8. End Sub

单独执行以上两段代码,执行效率差别不大,但如果存在多段代码,累积起来对程序的效率就会有较大的影响了。
4楼
罗刚君
5楼
wise
五、利用变量来减少对象读取次数
     如果一个变量在一个过程中多次出现,应考虑用一个变量来替换对象。因为变量存于内存中,VBA读取内存数据远远快于对象。
    如例子1:
  1. Sub a()
  2.   Dim T As Long, rng As Range
  3.   T = Timer
  4.   For Each rng In Range("A1:A2000")
  5.    If rng > [B1] Then rng.Interior.ColorIndex = 5
  6.   Next
  7.   [C1] = Format(Timer - T, "0.00") & "S"
  8. End Sub

在代码中,单元格B1 给引用了2000次,程序执行在我的电脑上是1.38S
例子2:
  1. Sub b()
  2.   Dim T As Long, rng As Range, st As Long
  3.   T = Timer
  4.   st = [B1]
  5.   For Each rng In Range("A1:A2000")
  6.    If rng > st Then rng.Interior.ColorIndex = 5
  7.   Next
  8.   [C2] = Format(Timer - T, "0.00") & "S"
  9. End Sub

在例子2代码中,单元格B1仅需要读取一次。在后面的循环中,单元格B1不再参与运算,而是在内存中的变量“标准”在参与运算。该运算速度是0.17S(我的电脑上)。
6楼
wise
六、善用带$的字符串处理函数
在VBA中,有两套字符串处理函数,包含带"$"和不带"$"的函数,例如mid 和mid$,Left 和Left$,Right 和Right$。
如果不使用带"$"符号的函数计算字符串,那么VBA将字符串作为变体数据来进行计算,而使用带"$"的函数时,则将字符串当作string类型来进行计算,显示变体型数据在计算时需要更多的内存空间。
如下面两段代码:
  1. Str=mid("Wise",2)
  2. Str=mid$("Wise",2)

第二句在执行效率上会占优势。
7楼
wise
六、善用带$的字符串处理函数
在VBA中,有两套字符串处理函数,包含带"$"和不带"$"的函数,例如mid 和mid$,Left 和Left$,Right 和Right$。
如果不使用带"$"符号的函数计算字符串,那么VBA将字符串作为变体数据来进行计算,而使用带"$"的函数时,则将字符串当作string类型来进行计算,显示变体型数据在计算时需要更多的内存空间。
如下面两段代码:
  1. Str=mid("Wise",2)
  2. Str=mid$("Wise",2)

第二句在执行效率上会占优势。
8楼
wise
七、循环中减少步长来提速
   当使用有针对性的For循环,即仅仅需要对循环对象中的部分对象进行操作时,应该调整循环的步长来减少循环的次数。
   对比下面两个例子:
   例子一:
  1. Sub T1()
  2.   tim = Timer
  3.   For i = 1 To 10000
  4.     If i Mod 2 = 1 Then Cells(i, 1).EntireRow.Interior.ColorIndex = 23
  5.   Next i
  6.   MsgBox Format(Timer - tim, "0.00") & "s"
  7. End Sub

该代码要循环次数是10000次
例子二:
  1. Sub T2()
  2.   tim = Timer
  3.   For i = 1 To 10000 Step 2
  4.      Cells(i, 1).EntireRow.Interior.ColorIndex = 23
  5.   Next i
  6.   MsgBox Format(Timer - tim, "0.00") & "s"
  7. End Sub

而例子二循环的次数是5000次。
实现同样的代码,但却循环的次数有差异,明显是代码二比代码一效率更高。
9楼
wise
八、利用数组代替单元格对象
VBA处理数组的速度远快于对象的速度,对于可以利用数组来替换对象都尽量使用数组。 以下两个例子来对比速度:
例子1:
  1. Sub 不及格()
  2.   Dim i As Integer, tim As Long
  3.   tim = Timer
  4.   For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
  5.      If Cells(i, 2) < 60 Then Cells(i, 3) = "不及格"
  6.   Next i
  7.   MsgBox Format(Timer - tim, "0.00") & "秒"
  8. End Sub

例子2:
  1. Sub b()
  2. Dim i As Long, tim As Long, arr1(), arr2()
  3. tim = Timer
  4. arr1 = Range([B2], Cells(Rows.Count, 2).End(xlUp))
  5. ReDim arr2(1 To UBound(arr1), 1 To 1)
  6. For i = 1 To UBound(arr1)
  7.    If arr1(i, 1) < 60 Then arr2(i, 1) = "不及格"
  8. Next i
  9. Range([c2], Cells(Rows.Count, 2).End(xlUp).Offset(0, 1)) = arr2
  10. MsgBox Format(Timer - tim, "0.00") & "秒"
  11. End Sub

一样的效果,但明显例子2的速度要比例子1的速度要快!
10楼
wangqilong1980
脚踏实地,慢慢往前爬
11楼
ANDY0393
谢谢lz分享,这些很实用,学习了

免责声明

有感于原ExcelTip.Net留存知识的价值及部分知识具有的时间限定性因素, 经与ExcelTip.Net站长Apolloh商议并征得其同意, 现将原属ExcelTip.Net的知识帖采集资料于本站点进行展示, 供有需要的人士查询使用,也慰缅曾经的论坛时代。 所示各个帖子的原作者如对版权有异议, 可与本人沟通提出,或于本站点留言,我们会尽快处理。 在此,感谢ExcelTip.Net站长Apolloh的支持,感谢本站点所有人**绿色风(QQ:79664738)**的支持与奉献,特此鸣谢!
------本人网名**KevinChengCW(QQ:1210618015)**原ExcelTip.Net总版主之一

评论列表
sitemap