遍历范围和更改数据的最快方法

quickest way to loop through range and change data

提问人:DonAndress 提问时间:11/3/2023 最后编辑:DonAndress 更新时间:11/3/2023 访问量:51

问:

我正在寻找一种最快的方法来遍历范围和更改数据。 假设我在 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
阵列 VBA 环路

评论

0赞 freeflow 11/3/2023
请发布您正在使用的实际代码。由于“ArrEmp)”中的错误,当前发布将无法运行
0赞 DonAndress 11/3/2023
tempRows 在那里只是为了描述我正在处理变量范围。出于测试目的,只需分配 tempRows = 100 或 sth。
0赞 Notus_Panda 11/3/2023
Freeflow在你的第一行代码中说,这已经会抛出一个错误。尝试复制粘贴而不是键入代码以避免这些问题(如果这是复制粘贴,则在实际代码中对其进行调整)。另外,请记住,在将来引用时,在声明变量时,您需要为每个变量使用类型,即 而不是因为 rng1 在最后一种情况下将是一个 Variant 变量。在这种情况下,这并不重要,因为它们都是变体,但是,没有必要使用 () 来获取数组。ArrEmp)Dim rng1 As Range, rng2 As RangeDim rng1, rng2 As Range
0赞 Notus_Panda 11/3/2023
此外,当将值作为数组获取时,您将获得一个具有维度的数组,因此请使用(其余的也是如此)。看看修复后是否出现任何错误。(1 To tempRows, 1 To 1)If arr(arrI,1) <> tempVal
0赞 DonAndress 11/3/2023
你是绝对正确的,很抱歉造成混乱。谢谢你的提示。那么在 100k 行范围内更改值的最快方法呢?您的建议是什么?

答:

0赞 FunThomas 11/3/2023 #1

a) 当您将数据从某个范围读取到数组中(并且该范围包含多个单元格)时,即使您仅从一列(或一行)读取数据,也始终会得到一个二维数组。第一个索引是行号,第二个索引是列号。如果对只有一个索引的二维数组进行寻址,则会出现下标超出范围错误

b) 在 VBA 中,数组可以在任何索引处开始和结束。但是,当您从某个范围读取数据时,返回数组的索引始终较低,即 1(对于两个维度),因此您的循环需要从 1 开始,而不是从 0 开始。最佳做法是不要对该索引进行硬编码,而是使用函数 LBoundUBound

因此,您的代码可能如下所示

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