分享

VBA利用数组优化代码运行效率

 L罗乐 2017-01-29

VBA让工作效率飞起来!

专门代写EXCEL VBA中小型 程序代码。

本人以诚信立足 ,另欢迎加友交流学习!



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

二、善用常量
如果某个数值或字符在程序中反复出现,则尽量声明一个产量来取代该值,在后面代码使用中直接调用常量。
具体看下例:

  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 这句代码通常放置在循环语句之前,在循环完成后再恢复屏幕更新,否则会影响正常工作。

四、利用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

单独执行以上两段代码,执行效率差别不大,但如果存在多段代码,累积起来对程序的效率就会有较大的影响了。

五、利用变量来减少对象读取次数
如果一个变量在一个过程中多次出现,应考虑用一个变量来替换对象。因为变量存于内存中,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(我的电脑上)。

六、善用带$的字符串处理函数
在VBA中,有两套字符串处理函数,包含带'$'和不带'$'的函数,例如mid 和mid$,Left 和Left$,Right 和Right$。
如果不使用带'$'符号的函数计算字符串,那么VBA将字符串作为变体数据来进行计算,而使用带'$'的函数时,则将字符串当作string类型来进行计算,显示变体型数据在计算时需要更多的内存空间。
如下面两段代码:

  1. Str=mid('Wise',2)

  2. Str=mid$('Wise',2)

第二句在执行效率上会占优势。

七、循环中减少步长来提速
当使用有针对性的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次。
实现同样的代码,但却循环的次数有差异,明显是代码二比代码一效率更高。

八、利用数组代替单元格对象
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的速度要快!


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多