2

我只是想通过一个(大)范围并用给定的替换值替换某些值(如果它们高于给定的最大值或低于给定的最小值......也是一个特定的字符)。

我的第一个想法是简单地遍历每个单元格并在必要时检查/替换。我觉得这个过程会很慢,我很好奇是否有更好的方法来完成这个。

每当我在 VBA 中编写与此类似的代码时,我都会看到每个单元格的值逐个单元格地改变,似乎必须有更好的方法。提前致谢。

编辑:

我什至还没有编写这个实现,因为我知道结果会是什么,如果可能的话,我宁愿做一些不同的事情,但这就是它的样子

For something
  If(Range.Value == condition)
    Range.Value = replacement_value
  Range = Range.Offset(a, b)
End For
4

2 回答 2

3

在单独的列中创建一个公式,然后copy/paste special, values only

= if(A2 > givenvalue; replace; if(A2< anothergivenvalue; anotherreplace; if (A2 = "particularcharacterortext"; replaceonemore; A2)))

将公式放在空列的空单元格中,将其拖动或复制/粘贴到整个列。之后,如果新的值没问题,copy/paste values only回到原来的位置。

于 2013-06-12T15:43:08.480 回答
2

以下 VBA 代码提供了一个简单的框架,您可以对其进行自定义以满足您的需求。它结合了您问题的评论中提到的许多优化,例如关闭屏幕更新并将比较从工作表移动到数组。

您会注意到宏进行了相当大的比较和替换。我运行它的数据集是 A1:Y100000 范围内 1 到 1000 之间的 250 万个随机数。如果一个数字大于 250 且小于 500,我将其替换为 0。这需要替换数据集中所有数字的 24.9%。

Sub ReplaceExample()

    Dim arr() As Variant
    Dim rng As Range
    Dim i As Long, _
        j As Long
    Dim floor as Long
    Dim ceiling as Long
    Dim replacement_value

    'assign the worksheet range to a variable
    Set rng = Worksheets("Sheet2").Range("A1:Y100000")
    floor = 250
    ceiling = 500
    replacement_value = 0

    ' copy the values in the worksheet range to the array
    arr = rng

    ' turn off time-consuming external operations
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    Application.EnableEvents = False

    'loop through each element in the array
    For i = LBound(arr, 1) To UBound(arr, 1)
        For j = LBound(arr, 2) To UBound(arr, 2) 
           'do the comparison of the value in an array element
           'with the criteria for replacing the value
           If arr(i, j) > floor And arr(i, j) < ceiling Then
                arr(i, j) = replacement
            End If
        Next j
    Next i

    'copy array back to worksheet range
    rng = arr

    'turn events back on
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True

End Sub  

我对不同的替代方案进行了一些性能测试,用于编码这个简单的比较和替换,我期望的结果与其他人的 VBA 性能结果一致。我将每个备选方案运行 10 次,计算每次运行的经过时间,并对 10 次经过的时间进行平均。

vba 性能结果

结果揭示了使用数组可能产生的巨大影响,尤其是当数据集很大时:与逐个测试和更改工作表单元格值的代码相比,数组操作——将数据集从工作表复制到数组,比较和更改数组值,然后将数组结果写回工作表——在这种情况下,平均运行时间减少了 98%,从 3.6 分钟减少到 4 秒。

虽然关闭外部事件的优化在工作表操作中产生了显着差异,运行时间减少了 22%,但当大多数计算工作是基于数组的时,这些优化几乎没有影响。

于 2013-06-12T20:54:01.177 回答