VBA listobject查找功能快
VBA listobject lookup function fast
我有几个 sheet 包含 ListObjects
当我必须在 listbject 中寻找相应的值时,我会做以下事情:
dim mytable as Listobject
set mytable = thisworkbook.sheets(x).listobject(1)
ValuetoSearch="whatever"
valueResult=""
' looking for the corresponding value of column A in column B
for i=1 to mytable.listrows.count
if mytable.listcolumns("A").databodyrange.item(i).value=ValuetoSearch then
valueResult=mytable.listcolumns("B").databodyrange.item(i).value
exit for
end if
next i
行得通。美好的。
但是:
这是最快的搜索方式吗?
当用户 select sheet 中的某些单元格(工作簿更改 select)时,我正在使用这些查找操作中的几个 "on the fly" 并且当 "you feel it" 这几乎是一秒钟的延迟,开始让用户感到厌烦。
干杯
谢谢
VBA 中的主要减速之一是 reading/writing 单元格值。您希望尽可能减少 read/write 访问工作表的次数。事实证明,在大多数情况下,将 运行ge 个值读入数组,然后对该数组进行计算,比对 运行 进行相同的计算要快得多价值观本身。
在您的情况下,您可以将 table 的 运行ge 读入数组(仅一次读取操作),而不是对每一行执行读取操作。
Dim mytable As ListObject
Dim myArr() As Variant
Set mytable = ThisWorkbook.Sheets(x).ListObject(1)
valuetosearch = "whatever"
valueResult = ""
myArr = mytable.Range.Value 'Read entire range of values into array
' looking for the corresponding value of column A in column B
For i = 1 To mytable.ListRows.Count
If myArr(i, 1) = valuetosearch Then 'Check the value of the ith row, 1st column
valueResult = myArr(i,2) 'Get the value of the ith row, 2nd column
Exit For
End If
Next i
我 运行 对具有 1,000,000 行的 table 进行快速基准测试,并且搜索值仅出现在最后一行(最坏的可能情况)。您的原始代码需要 4.201 秒,而这个代码需要 0.484 秒。这快了将近 9 倍!
如果您的数据在工作表上,那么Application.Match()
非常快:
Sub Tester()
Dim m, rng, t
Set rng = ThisWorkbook.Sheets(1).ListObjects(1).ListColumns(1).DataBodyRange
t = Timer()
m = Application.Match("Val_1", rng, 0) 'on the first row...
Debug.Print m, Timer - t 'approx 0 sec
t = Timer()
m = Application.Match("Val_1000000", rng, 0) 'on the last row...
Debug.Print m, Timer - t 'approx 0.03 to 0.05 sec
End Sub
m
将是匹配行的索引,如果不匹配则为错误 - 您可以使用 IsError(m)
进行测试
我有几个 sheet 包含 ListObjects
当我必须在 listbject 中寻找相应的值时,我会做以下事情:
dim mytable as Listobject
set mytable = thisworkbook.sheets(x).listobject(1)
ValuetoSearch="whatever"
valueResult=""
' looking for the corresponding value of column A in column B
for i=1 to mytable.listrows.count
if mytable.listcolumns("A").databodyrange.item(i).value=ValuetoSearch then
valueResult=mytable.listcolumns("B").databodyrange.item(i).value
exit for
end if
next i
行得通。美好的。 但是:
这是最快的搜索方式吗? 当用户 select sheet 中的某些单元格(工作簿更改 select)时,我正在使用这些查找操作中的几个 "on the fly" 并且当 "you feel it" 这几乎是一秒钟的延迟,开始让用户感到厌烦。
干杯 谢谢
VBA 中的主要减速之一是 reading/writing 单元格值。您希望尽可能减少 read/write 访问工作表的次数。事实证明,在大多数情况下,将 运行ge 个值读入数组,然后对该数组进行计算,比对 运行 进行相同的计算要快得多价值观本身。
在您的情况下,您可以将 table 的 运行ge 读入数组(仅一次读取操作),而不是对每一行执行读取操作。
Dim mytable As ListObject
Dim myArr() As Variant
Set mytable = ThisWorkbook.Sheets(x).ListObject(1)
valuetosearch = "whatever"
valueResult = ""
myArr = mytable.Range.Value 'Read entire range of values into array
' looking for the corresponding value of column A in column B
For i = 1 To mytable.ListRows.Count
If myArr(i, 1) = valuetosearch Then 'Check the value of the ith row, 1st column
valueResult = myArr(i,2) 'Get the value of the ith row, 2nd column
Exit For
End If
Next i
我 运行 对具有 1,000,000 行的 table 进行快速基准测试,并且搜索值仅出现在最后一行(最坏的可能情况)。您的原始代码需要 4.201 秒,而这个代码需要 0.484 秒。这快了将近 9 倍!
如果您的数据在工作表上,那么Application.Match()
非常快:
Sub Tester()
Dim m, rng, t
Set rng = ThisWorkbook.Sheets(1).ListObjects(1).ListColumns(1).DataBodyRange
t = Timer()
m = Application.Match("Val_1", rng, 0) 'on the first row...
Debug.Print m, Timer - t 'approx 0 sec
t = Timer()
m = Application.Match("Val_1000000", rng, 0) 'on the last row...
Debug.Print m, Timer - t 'approx 0.03 to 0.05 sec
End Sub
m
将是匹配行的索引,如果不匹配则为错误 - 您可以使用 IsError(m)