Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 范围()VS单元格()-运行时间_Performance_Vba_Excel - Fatal编程技术网

Performance 范围()VS单元格()-运行时间

Performance 范围()VS单元格()-运行时间,performance,vba,excel,Performance,Vba,Excel,我在这个网站上看到很多VBA代码使用Range方法和For循环: Range("A" & i) 与正确的单元格命令相反: Cells(i,1) 我一直知道单元格的方式更快,部分原因是范围解析时间更长,部分原因是串联(&)是一个相对缓慢的过程(与任何其他简单的算术运算-AFAIK相反) 所以,问题是,它真的更快吗?多少钱?有时,范围格式更具可读性,特别是对于新手。速度的提高是否证明了回答中的轻微不适和必要的额外解释是合理的?我做了一些测试,看看是什么 方法 我已经测试了四种场景的速度。

我在这个网站上看到很多VBA代码使用
Range
方法和
For
循环:

Range("A" & i)
与正确的
单元格
命令相反:

Cells(i,1)
我一直知道
单元格
的方式更快,部分原因是
范围
解析时间更长,部分原因是串联(
&
)是一个相对缓慢的过程(与任何其他简单的算术运算-AFAIK相反)


所以,问题是,它真的更快吗?多少钱?有时,
范围
格式更具可读性,特别是对于新手。速度的提高是否证明了回答中的轻微不适和必要的额外解释是合理的?

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

方法 我已经测试了四种场景的速度。每项测试包括一个进行100000次循环的For循环。测试的核心是使用with语句“抓取”一个单元格

四项测试分别为:

  • 单元格,可变单元格-
    带单元格(i,1)

  • 单元格,单单元格-
    带单元格(1,1)

  • 范围,可变单元格-
    带范围(“A”&i)

  • 范围,单单元格-
    范围(“A1”)

我对这四个测试用例使用了单独的sub,并使用了第五个sub来运行它们中的每一个500次。请参阅下面的代码

对于时间测量,我使用GetTickCount获得毫秒精度

结果 从500次测量中,结果相当一致。(我已经用100次迭代多次运行了它,结果基本相同。)

解读
单元格
方法比等效的
范围
方法快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