Performance 范围()VS单元格()-运行时间
我在这个网站上看到很多VBA代码使用Performance 范围()VS单元格()-运行时间,performance,vba,excel,Performance,Vba,Excel,我在这个网站上看到很多VBA代码使用Range方法和For循环: Range("A" & i) 与正确的单元格命令相反: Cells(i,1) 我一直知道单元格的方式更快,部分原因是范围解析时间更长,部分原因是串联(&)是一个相对缓慢的过程(与任何其他简单的算术运算-AFAIK相反) 所以,问题是,它真的更快吗?多少钱?有时,范围格式更具可读性,特别是对于新手。速度的提高是否证明了回答中的轻微不适和必要的额外解释是合理的?我做了一些测试,看看是什么 方法 我已经测试了四种场景的速度。
Range
方法和For
循环:
Range("A" & i)
与正确的单元格
命令相反:
Cells(i,1)
我一直知道单元格
的方式更快,部分原因是范围
解析时间更长,部分原因是串联(&
)是一个相对缓慢的过程(与任何其他简单的算术运算-AFAIK相反)
所以,问题是,它真的更快吗?多少钱?有时,
范围
格式更具可读性,特别是对于新手。速度的提高是否证明了回答中的轻微不适和必要的额外解释是合理的?我做了一些测试,看看是什么
方法
我已经测试了四种场景的速度。每项测试包括一个进行100000次循环的For循环。测试的核心是使用with语句“抓取”一个单元格
四项测试分别为:
- 单元格,可变单元格-
带单元格(i,1)
- 单元格,单单元格-
带单元格(1,1)
- 范围,可变单元格-
带范围(“A”&i)
- 范围,单单元格-
范围(“A1”)
单元格
方法比等效的范围
方法快2.6倍。如果使用串联,则会增加10%的执行时间,这使差异几乎增加3倍。这是一个巨大的差异
然而,另一方面,我们谈论的是每个单元操作的平均时间为0.001 ms,而不是0.004 ms。除非我们在超过2-30万个单元上运行脚本,否则这不会产生明显的速度差异
结论
是的,有一个巨大的速度差
不,我不想麻烦告诉人们使用细胞方法,除非他们处理大量的细胞
试验装置
- Win7 64位
- 8GB内存
- 英特尔酷睿i7-3770@3.40 GHz
- Excel 2013 32位
在看到
.Cells(1,“A”)
表示法的示例后,我对测试进行了扩展,我认为这可能是.Range(“A1”)
的可读性与.Cells(1,1)
我测试了读写操作,发现在读操作中,.Cells(1,“A”)
在.Range(“A1”)
和.Cells(1,1)
在.Range(“A1”)
的一半时间内执行。对于写入,差异较小(分别约88%和82%)
代码:
^手工抄写,可能包含打字错误
平台:Excel 2013 32位
Windows 7 64位
16GB内存
至强E5-1650 v2@3.5GHz
(编辑:在代码的编写部分将“x”更改为“y”,请参见手写代码的免责声明!)值得链接此堆栈溢出问题,进一步解释如何提高性能:
干得好。你介意用
单元格(i,“A”)
的线条运行另一个测试吗?有趣的是,我现在就这么做。谢谢!:)@Ralph提出了180 ms,这比原始的细胞
溶液慢一些,但肯定比范围
方法快。我明天会在重新运行几次后更新我的答案。请您将范围(“A1”)。偏移量(I-1,0)
与单元格(I,1)
进行比较。最快的读数应该是数组读数的范围。也许更好的基准是使用各种方法设置一个1000×1000的表,其中包含值。通过我的测试,用值填充表Range(“top”)。偏移量(i,j)
产生34800个单元/秒,单元(i,j)
35000个单元/秒和内存阵列1780500个单元/秒。
For i = 1 To 100000
With Cells(i, 1)
End With
Next i
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
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
Option Explicit
Sub test()
Dim i, x, y, a, t1, t2, t3, t4
x=1000000
y=x/100
Debug.Print "---Read---" 'Cell A1 contains the number 55
t1=Timer*1000
For i = 1 to x
a = Sheet1.Range("A1")
Next
t2=Timer*1000
Debug.Print t2 - t1 & "ms"
For i = 1 to x
a = Sheet1.Cells(1, "A")
Next
t3=Timer*1000
Debug.Print t3 - t2 & "ms (" & Round(100*(t3-t2)/(t2-t1),1)&"%)"
For i = 1 to x
a = Sheet1.Cells(1, "A")
Next
t4=Timer*1000
Debug.Print t4 - t3 & "ms (" & Round(100*(t4-t3)/(t2-t1),1)&"%)"
Debug.Print "---Write---"
a=55
t1=Timer*1000
For i = 1 to y
Sheet1.Range("A1") = a
Next
t2=Timer*1000
Debug.Print t2 - t1 & "ms"
For i = 1 to y
Sheet1.Cells(1, "A") = a
Next
t3=Timer*1000
Debug.Print t3 - t2 & "ms (" & Round(100*(t3-t2)/(t2-t1),1)&"%)"
For i = 1 to y
Sheet1.Cells(1, "A") = a
Next
t4=Timer*1000
Debug.Print t4 - t3 & "ms (" & Round(100*(t4-t3)/(t2-t1),1)&"%)"
Debug.Print "----"
End Sub