Range()VS Cells() - 运行时间

时间:2016-03-18 00:14:00

标签: performance vba excel-vba excel

我使用带有Range循环的For方法在此网站上看到了很多VBA代码:

Range("A" & i)

与正确的Cells命令相反:

Cells(i,1)

我总是知道Cells方式更快,部分原因是因为Range需要更长的时间来解决,部分原因是连接(&)是一个相对缓慢的过程(与其他任何方式相反)简单的算术运算 - AFAIK)。

所以,问题是,真的更快吗?多少钱?有时,Range格式更具可读性,特别是对于新手。速度增益是否证明了轻微的不适以及回复中必要的额外解释?

3 个答案:

答案 0 :(得分:20)

我做了一些测试,看看是什么。

方法

我测试了四种情况的速度。每个测试由For循环组成,进行100 000次循环。测试的核心是使用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")

我在四个测试用例中使用了单独的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

Measurement results

解释

Cells方法比同等Range方法快2.6倍。如果正在使用连接,则会增加10%的执行时间,这差异几乎是3倍。这是一个巨大的差异。

另一方面,我们谈论的是每个电池操作平均0.001 ms VS 0.004 ms。除非我们在超过2-3万个单元格上运行脚本,否则这不会产生明显的速度差异。

结论

是的,速度差异很大。

不,我不打算告诉人们使用Cell方法,除非他们处理大量的细胞。

测试设置

  • Win7 64位
  • 8 GB RAM
  • 英特尔酷睿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

答案 1 :(得分:3)

在看到.Cells(1, "A")符号的示例之后我扩展了测试,我认为这可能是.Range("A1")的可读性与.Cells(1, 1)的速度之间的良好平衡

我测试了读取和写入,并且发现了读取,.Cells(1, "A")在约{69}的.Range("A1")执行,.Cells(1, 1).Range("A1")的一半时间内执行。对于写入,差异较小(分别为~88%和82%)。

代码:

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

^手工转录,可能包含错别字......

平台:
 Excel 2013 32位
 Windows 7 64位
 16GB拉杆
 Xeon E5-1650 v2 @ 3.5GHz

(编辑:在代码的写入部分将“x”更改为“y” - 请参阅关于手工输入代码的免责声明!)

答案 2 :(得分:0)

值得链接这个堆栈溢出问题,它进一步解释了如何提高性能:

Slow VBA macro writing in cells