这些新颖的方式[可能是最好的方式吗?]在VBA中引用动态单元?

Ana*_*a 秀 8 excel vba reference excel-vba

我们通常使用表达式:Cells(i, 1),, Cells(i, "A")Range("A" & i)在VBA中引用动态单元格,但我发现以下奇怪的代码也有效:

Sub Test1()
For i = 1 To 10000
    Range("A1")(i) = i   
Next
End Sub
Run Code Online (Sandbox Code Playgroud)

我还发现使用方括号[]来表示单元格的快捷符号(是的,我知道表达EVALUATE命令的简写方法)也可以在这里使用,如下面的代码

Sub Test2()
For i = 1 To 10000
    [A1].Resize(1000, 1)(i) = i   
Next
End Sub
Run Code Online (Sandbox Code Playgroud)

要么

Sub Test3()
For i = 1 To 10000
    [A1].Offset(i - 1) = i   
Next
End Sub
Run Code Online (Sandbox Code Playgroud)

与流行的看法相反,方括号只能用快捷符号表示固定范围.我测试了所有这些,他们返回了相同的输出.

老实说,我从来没有想过这三个表达式都存在过,所以我猜它们可能是新的.这是真的吗?


我不仅找到了它们,还测试了它们以确定哪一个是最好的.最好的我的意思是他们使用计时测试的表现.我测试了这些陈述:

  1. Cells(i, 1) = Rnd
  2. Range("A" & i) = Rnd
  3. Cells(i, "A") = Rnd
  4. Range("A1")(i) = Rnd
  5. [A1].Resize(1000, 1)(i) = Rnd
  6. [A1].Offset(i - 1) = Rnd

到以下代码

Sub Test()
Dim i As Long

Randomize
For i = 1 To 1000        'I also tested them with 10,000 loops
    'Put the expression here
Next
End Sub
Run Code Online (Sandbox Code Playgroud)

我获得了在我的机器上完成的持续时间,如下所示

1,000 loops
1               2               3               4               5               6
0.290110725     0.298291317     0.305540433     0.289084126     0.325044276     0.318445433
0.270974218     0.287950980     0.276009685     0.277133638     0.318741694     0.312968414
0.277361318     0.274790389     0.273291810     0.275994401     0.311879789     0.312000675
0.279113453     0.275501647     0.275247422     0.281113426     0.311558662     0.315628943
0.270359637     0.276440868     0.279950951     0.276444561     0.320118775     0.311556754
0.270066136     0.281525061     0.273649022     0.276767648     0.311083246     0.311015128
0.274146235     0.277156933     0.274465750     0.287375210     0.311426416     0.319849274
0.269184843     0.277200430     0.276525859     0.276931561     0.322461782     0.310902381
0.271190611     0.283046575     0.280286123     0.275876294     0.312358236     0.313066500
0.271210909     0.277953463     0.274105173     0.276916590     0.312845710     0.321566549

Average time
0.274371809     0.280985766     0.278907223     0.279363746     0.315751859     0.314700005
Run Code Online (Sandbox Code Playgroud)

10,000 loops
1               2               3               4               5               6
1.897854697     1.975970014     2.026380540     1.963044684     2.667340257     2.404596752
1.893136200     1.958722430     1.997488630     1.957524600     2.412742475     2.364692000
1.915567238     1.991447404     2.026974359     1.972207855     2.396174991     2.408500400
1.885336683     1.964379644     2.001175971     1.950138292     2.362537378     2.369196417
1.889658641     1.959677449     1.998453783     1.984470995     2.372677528     2.366525087
1.885327819     1.963668734     1.997487505     2.038683070     2.367691027     2.380044796
1.878379741     1.958654295     2.002764956     2.008183347     2.368766984     2.362091273
1.894069516     1.960857991     1.994435035     2.031241378     2.377953481     2.367554909
1.894528017     1.972240515     2.003587552     1.961539277     2.364523191     2.373092790
1.883387443     1.965169572     1.999893716     1.948455660     2.363346303     2.368680396


Average time
1.891724600     1.967078805     2.004864205     1.981548916     2.405375362     2.376497482
Run Code Online (Sandbox Code Playgroud)

基于这两个结果,虽然结果是不确定的,用于比较表达式:Range("A" & i),Cells(i, "A"),和Range("A1")(i)也用于比较[A1].Resize(1000, 1)(i)[A1].Offset(i - 1),原来最快的性能Cells(i, 1).一般来说这是真的吗?为什么这样?我的猜测是在运行时VBA总是使用Cells(i, 1),所以当编译代码时,其他表达式中的所有引用必须转换为表达式1,因为我坚信VBA必须记住它的编译版本的代码和我们用来写的任何表达式我们的代码.但这只是我的猜测.

GSe*_*erg 5

以下奇怪的代码

并不是的.代码并不奇怪.
问题是,Range变量是纸张的"视口"而不是带有混凝土墙的固定盒子.你绝对可以超越你最初定义的范围Range.

这条线

Range("A1")(i) = i
Run Code Online (Sandbox Code Playgroud)

相当于

Range("A1").Cells(i).Value = i
Run Code Online (Sandbox Code Playgroud)

这是完全可行的,即使Range("A1")只包含一个单元格 - 你只是超越了那个单元格.

我从没想过这三个表达式都存在,所以我猜他们可能是新的.这是真的吗?

不,这不对.他们很老了.我手边最古老的办公室是2003年,它在那里工作,我非常有信心它曾经在Office 95中工作.

你从未听说过他们的原因可能是因为没有人使用它们,这可能是件好事.虽然它们从对象模型的角度来看是有效的,但它们比更直接的方式更令人困惑.

事实证明,最快的表现是Cells(i, 1).一般来说这是真的吗?为什么这样?

我从未测试过(我不会),但逻辑上Cells(i, 1)应该是最快的,因为它不涉及字符串解析和/或评估.可以说,所有其他选项最终都会调用Cells(i, 1).