在条件范围内有条件地更改值的最有效方法?

时间:2013-06-12 15:35:23

标签: excel vba excel-vba

我只是希望在一个(大)范围内运行并使用给定的替换值替换某些值(如果它们高于给定的最大值或低于给定的最小值...也是一个特定的字符)。

我的第一个想法是简单地遍历每个细胞并在必要时检查/更换。我觉得这个程序虽然很慢,但我很好奇是否有更好的方法来实现这个目标。

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

编辑:

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

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

2 个答案:

答案 0 :(得分:3)

在单独的列中创建公式,然后copy/paste specialvalues only

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

将公式放在空列中的空单元格中,拖动它或复制/粘贴到整个列。之后,如果新值正常,copy/paste values only到原始位置。

答案 1 :(得分:0)

以下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 performance results

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

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