我做了一些测试,看看是什么。
方法
我测试了四种场景的速度。每个测试都包含一个执行 100 000 次循环的 For 循环。测试的核心是使用 with 语句来“抓取”一个单元格。
For i = 1 To 100000
With Cells(i, 1)
End With
Next i
四个测试是:
单元格,可变单元格 - With Cells(i, 1)
细胞,单细胞 - With Cells(1, 1)
范围,可变单元格 - With Range("A" & i)
范围,单个单元格 - Range("A1")
我为四个测试用例使用了单独的子程序,并使用了第五个子程序将它们中的每一个运行了 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
解读
Cells 方法比等效的 Range 方法快 2.6 倍。如果使用连接,这会增加 10% 的执行时间,这使得差异几乎是 3 倍。这是一个巨大的差异。
另一方面,我们谈论的是平均 0.001 ms VS 0.004 ms 每个单元操作。除非我们在超过 2-30 万个单元上运行脚本,否则这不会产生明显的速度差异。
结论
是的,速度差异很大。
不,我不会告诉人们使用 Cells 方法,除非他们处理大量细胞。
测试设置
- Win7 64 位
- 8 GB 内存
- 英特尔酷睿 i7-3770 @ 3.40 GHz
- Excel 2013 32 位
我错过了什么吗?我搞砸了什么吗?请不要犹豫指出来!干杯! :)
代码
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