我知道这一点;
Arr() =Range("E2:X2500")
然后用Arr做一些事情,然后用倒回去
Range("E2:X2500")=Arr()
比直接循环和引用单元格效率高出许多倍(更快(。这是光速
但是,这种从范围到数组的赋值只获取单元格的值。有没有一种方法可以将实际范围(连续或不连续(分配到阵列(具有相同的光速(中,这样你就可以像对待细胞一样对待阵列项目,比如:
arr(23).row 'getting a row number
或者;
If Arr(23).Value ="Pending" then arr(23).font.bold=1 else arr(23).font.bold=0
我知道我可以调暗一个范围类型的数组,其中每个项目可以存储一个实际的单个单元格范围。但这个数组不能用同样的方式处理——只有一个线性赋值:
Dim Arr () as Range
Set Arr = Range("E2:X2500") 'error
相反,我需要迭代每个单元格,并将其分配给范围类型数组中的下一个项,将允许我以引用单元格的方式处理项,但在处理循环时,加载时间要长得多。
此外,我如何像一行赋值一样轻松有效地将范围类型数组转储回工作表?我认为唯一的方法是再次使用循环,对吗
附带问题:从速度上讲,通过范围型数组引用单元格比直接通过表格引用单元格好吗?还是两者基本相同?
谢谢!
好吧,使用数组将节省大量代码运行时间。但是,有一些问题必须理解:
-
当VBA和项目的工作量增加时,第一件事就是正确地声明变量。试着做一个反射,把
Option Explicit
放在所有模块的顶部。在数组的情况下,从这个角度来看,事情是这样的:Dim Arr() As variant, arr1 As Variant
这两个声明都在excel中工作。但第二个是推荐的(关于麦味(,当你需要一个范围的数组时。当您想要构建一个结果数组时,比如说,它将是从零开始的,并且您必须注意返回值的范围大小。
-
在未修复/元素数量未知的情况下,无法像您在问题中尝试的那样检索数组内容。看看下一个测试代码:
Sub testArrays() Dim sh As Worksheet, rng As Range, arrTest As Variant Set sh = ActiveSheet Set rng = sh.Range("A1:F4") arrTest = rng.value sh.Range("J1").Resize(UBound(arrTest, 1), UBound(arrTest, 2)).value = arrTest End Sub
建议使用arrTest = sh.Range("A1:F4").value
。使用范围Value
。Excel能够根据您的声明理解您需要什么,但它有助于您以某种方式与范围定义的方式进行区分。
有时,您需要在分析动态范围的过程中构建一个数组。如果您无法知道新的数组维度,并且需要Redim(Preserve(,在这种情况下,只能重新确定数组的第二个维度,并且必须使用Transpose
函数。最后,只有知道数组的行数和列数,才能在一定范围内正确加载得到的数组。
- 您可以通过以下方式从数组行推断出范围行:如果我们参考上面的
arrTest
,我们知道它的第一行是表的第一行,它有5列
因此,arrTest(3, 1)
将是sh.Range("A3").Value
,其行将是3。
那么,arrTest(3, 4)
将是sh.Range("D3").Value
,并且其行也将是3。
如果数组来自从第五行开始的范围,则必须加四才能获得从数组行提取的表行。。。
因此,您的示例可以转换为:
If arrTest(3, 4) ="Pending" then sh.Cells(3, 4).Font.Bold=1 Else sh.Cells(3, 4).Font.Bold=0
-
现在,如果您需要一个range数组,则无法按照您尝试的方式进行。您必须使用范围地址并在末尾构建范围:
Sub testArraysBis() Dim sh As Worksheet, rng As Range, rng1 As Range, lastCol As Long Dim rng2, arrTest As Variant, arrT As Variant, arrF As Variant Set sh = ActiveSheet lastCol = sh.Cells(1, Cells.Columns.Count).End(xlToLeft).column Set rng = sh.Range(sh.Cells(1, 1), sh.Cells(4, lastCol)) Set rng1 = sh.Range("A5:F6") arrT = Array(rng.Address, rng1.Address) arrTest = rng.value Debug.Print UBound(arrTest), LBound(arrTest) sh.Range("J1").Resize(UBound(arrTest, 1), UBound(arrTest, 2)).value = arrTest Set rng2 = sh.Range(arrT(0)) Debug.Print rng2.Address arrF = sh.Range(arrT(0)).value Debug.Print UBound(arrF, 2) End Sub
rng2
范围将使用从arrT
数组中提取的地址字符串构建。还可以从arrT
第一元素中提取数组(arrF
(。。。
- Epilog:就速度而言,最好的方法是在数组中加载范围,使用它们进行所有处理(在内存中,由于这一方面,处理速度非常快(,但最重要的问题是使用
Union
构建另一个数组(甚至一个范围(,并立即检索数据。将每个部分处理结果发送到一个单元格/范围会消耗大量时间和其他资源,因为范围很大