vac*_*cip 12 excel performance vba excel-vba
我在这个站点上看到了很多使用循环Range方法的VBA代码For:
Range("A" & i)
Run Code Online (Sandbox Code Playgroud)
与正确的Cells命令相反:
Cells(i,1)
Run Code Online (Sandbox Code Playgroud)
我总是知道Cells方式更快,部分是因为Range需要更长时间才能解决,部分原因是连接(&)是一个相对缓慢的过程(与任何其他简单的算术操作相反 - AFAIK).
所以,问题是,它真的更快吗?多少钱?有时,Range格式更具可读性,特别是对于新手.速度增益是否证明了轻微的不适以及回复中必要的额外解释?
vac*_*cip 20
我做了一些测试,看看是什么.
我测试了四种情况的速度.每个测试由For循环组成,进行100 000次循环.测试的核心是使用with语句"抓住"一个单元格.
For i = 1 To 100000
With Cells(i, 1)
End With
Next i
Run Code Online (Sandbox Code Playgroud)
四项测试是:
细胞,可变细胞 - With Cells(i, 1)
细胞,单细胞 - With Cells(1, 1)
范围,可变细胞 - With Range("A" & i)
范围,单细胞 - Range("A1")
我已经为四个测试用例使用了单独的subs,并使用了第五个sub来运行它们500次.请参阅下面的代码.
对于时间测量,我使用GetTickCount来获得毫秒精度.
从500次测量,结果非常一致.(我已经多次运行100次迭代,结果几乎相同.)
Cells Cells Range Range
(variable) (single) (variable) (single)
avg 124,3 126,4 372,0 329,8
median 125 125 374 328
mode 125 125 374 328
stdev 4,1 4,7 5,7 5,4
min 109 124 358 327
max 156 141 390 344
Run Code Online (Sandbox Code Playgroud)
该Cells方法比同等Range方法快2.6倍.如果正在使用连接,则会增加10%的执行时间,这差异几乎是3倍.这是一个巨大的差异.
另一方面,我们谈论的是每个电池操作平均0.001毫秒VS 0.004毫秒.除非我们在超过2-3万个单元上运行脚本,否则这不会产生明显的速度差异.
是的,速度差异很大.
不,我不打算告诉人们使用Cells方法,除非他们处理大量的细胞.
我错过了什么吗?我翘起来了吗?请不要犹豫,指出来!干杯! :)
Public Declare Function GetTickCount Lib "kernel32.dll" () As Long
Sub testCells(j As Long)
Dim i As Long
Dim t1 As Long
Dim t2 As Long
t1 = GetTickCount
For i = 1 To 100000
With Cells(i, 1)
End With
Next i
t2 = GetTickCount
Sheet4.Cells(j, 1) = t2 - t1
End Sub
Sub testRange(j As Long)
Dim i As Long
Dim t1 As Long
Dim t2 As Long
t1 = GetTickCount
For i = 1 To 100000
With Range("A" & i)
End With
Next i
t2 = GetTickCount
Sheet4.Cells(j, 2) = t2 - t1
End Sub
Sub testRangeSimple(j As Long)
Dim i As Long
Dim t1 As Long
Dim t2 As Long
t1 = GetTickCount
For i = 1 To 100000
With Range("A1")
End With
Next i
t2 = GetTickCount
Sheet4.Cells(j, 3) = t2 - t1
End Sub
Sub testCellsSimple(j As Long)
Dim i As Long
Dim t1 As Long
Dim t2 As Long
t1 = GetTickCount
For i = 1 To 100000
With Cells(1, 1)
End With
Next i
t2 = GetTickCount
Sheet4.Cells(j, 4) = t2 - t1
End Sub
Sub runtests()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim j As Long
DoEvents
For j = 1 To 500
testCells j
Next j
DoEvents
For j = 1 To 500
testRange j
Next j
DoEvents
For j = 1 To 500
testRangeSimple j
Next j
DoEvents
For j = 1 To 500
testCellsSimple j
Next j
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
For j = 1 To 5
Beep
DoEvents
Next j
End Sub
Run Code Online (Sandbox Code Playgroud)