提问人:DonAndress 提问时间:11/3/2023 最后编辑:DonAndress 更新时间:11/3/2023 访问量:51
遍历范围和更改数据的最快方法
quickest way to loop through range and change data
问:
我正在寻找一种最快的方法来遍历范围和更改数据。 假设我在 Range(“A1:A” & tempRows) 中有字符串,并且根据值 (<>tempVal) 我想更改相应单元格 Range(“B1:B” & tempRows) 中的值。 我有大约 100k 行。 使用 IF 通过 For-Next 循环执行此操作需要相当长的时间。 我正在考虑数组并以这种方式更改值,并且仅在 1 个数组中更改很容易(对于数组中的每个项目),但比较另一个数组中的值并不那么容易。我不知道如何在不循环 For-Next 的情况下获取数组索引。
有什么建议吗?
另外,由于某种原因,以下代码不起作用,我收到下标超出范围错误:
Dim Arr(), arrEmp() as variant
arr = Range("A1:A" & tempRows).value
arrEmp = Range("B1:B" & tempRows).value
for arrI = 0 to tempRows - 1
if arr(arrI) <> tempVal and arrEmp(arrI) = 0 then arrEmp(arrI) = 1
next
答:
0赞
FunThomas
11/3/2023
#1
a) 当您将数据从某个范围读取到数组中(并且该范围包含多个单元格)时,即使您仅从一列(或一行)读取数据,也始终会得到一个二维数组。第一个索引是行号,第二个索引是列号。如果对只有一个索引的二维数组进行寻址,则会出现下标超出范围错误。
b) 在 VBA 中,数组可以在任何索引处开始和结束。但是,当您从某个范围读取数据时,返回数组的索引始终较低,即 1(对于两个维度),因此您的循环需要从 1 开始,而不是从 0 开始。最佳做法是不要对该索引进行硬编码,而是使用函数 LBound
和 UBound
因此,您的代码可能如下所示
Dim arr() As Variant, arrEmp() As Variant
With ActiveSheet
arr = .Range("A1:A" & tempRows).Value
arrEmp = .Range("B1:B" & tempRows).Value
Dim row As Long, col As Long
For row = LBound(arr, 1) To UBound(arr, 1)
For col = LBound(arr, 2) To UBound(arr, 2)
If arr(row, col) <> tempVal And arrEmp(row, col) = 0 Then
arrEmp(row, col) = 1
End If
Next col
Next row
.Range("B1:B" & tempRows).Value = arrEmp
End With
评论
0赞
DonAndress
11/3/2023
哦。。。所以 a) 和 b) 是非常关键的信息!非常感谢。但还有一个 - 一般来说,这是最快的方法,不仅使用数组,而且在 100k 行的范围内更改值?我正在寻找最好的解决方案。
0赞
FunThomas
11/3/2023
是的。这是迄今为止最快(也是最干净)的方法。
0赞
DonAndress
11/3/2023
让我报告一下 - 在我的 ~50k 行的测试文件中,For-Each-Next 解决方案需要 72 秒,您的数组解决方案需要 ~1.2 秒。还不错;)再次感谢您的帮助!
0赞
freeflow
11/4/2023
如果您可以使用 twinBasic,VB6/VBA 的替代品,可能会更快。nolongerset.com/create-com-addin-with-twinbasic
下一个:需要帮助了解...OF 循环
评论
ArrEmp)
Dim rng1 As Range, rng2 As Range
Dim rng1, rng2 As Range
(1 To tempRows, 1 To 1)
If arr(arrI,1) <> tempVal