Excel的优化

时间:2013-09-17 07:04:26

标签: excel optimization excel-vba vba

以下是情况:在我的Excel工作表中,我有一个列,其中包含1-name形式的条目。我想删除这些数字,考虑到这个数字也可以是两位数。这本身并不是一个问题,我让它工作,只是性能是如此糟糕。因为现在我的程序每个单元格需要大约半秒钟。

我的问题:如何改善表现? 这是代码:

Sub remove_numbers()
    Dim YDim As Long
    Dim i As Integer, l As Integer
    Dim val As String
    Dim s As String
    YDim = Cells(Rows.Count, 5).End(xlUp).Row
    For i = 8 To YDim
        val = Cells(i, 5)
        l = Len(val)
        s = Mid(val, 2, 1)
        If s = "-" Then
            val = Right(val, l - 2)
        Else
            val = Right(val, l - 3)
        End If
        Cells(i, 5).Value = val
    Next i
End Sub

4 个答案:

答案 0 :(得分:4)

不是使用3个不同的函数:Len(),Mid(),Right(),你可以使用Split()函数,在这种情况下效率会更高。

尝试以下代码

Sub remove_numbers()
    Application.ScreenUpdating = False
    Dim i As Long
    For i = 8 To Cells(Rows.Count, 5).End(xlUp).Row
        Cells(i, 5) = Split(Cells(i, 5), "-")(1)
    Next i
    Application.ScreenUpdating = True
End Sub

答案 1 :(得分:3)

我的建议:

Sub remove_numbers()
    Dim i As Integer, values() As Variant
    values = Range(Cells(8, 5), Cells(Rows.Count, 5).End(xlUp).Row).Value
    For i = LBound(values) To UBound(values)
        values(i, 1) = Mid(values(i, 1), IIf(Mid(values(i, 1), 2, 1) = "-", 2, 3))
    Next
    Range(Cells(8, 5), Cells(Rows.Count, 5).End(xlUp).Row).Value = values
End Sub

优化:

  • 在内存中执行所有计算并更新整个范围:这是一个巨大的性能提升;
  • 将多个命令压缩为单个命令;
  • Right(x, Len(x)-n)替换为Mid(x, n)

编辑:

正如@Mehow建议的那样,你也可以使用

获得一些表现
 values(i, 1) = Split(values(i, 1), "-", 2)(1)

而不是values(i, 1) = Mid(values(i, 1), IIf(Mid(values(i, 1), 2, 1) = "-", 2, 3))

答案 2 :(得分:1)

您应该将整个范围值作为数组进行操作,并在内存中直接使用它。

类似的东西:

Dim valuesOfRangeToModify() As Variant
Set valuesOfRangeToModify = Range(Cells(8, 5), Cells(Rows.Count, 5).End(xlUp)).Value
For Each cell In valuesOfRangeToModify 
    cell = ... // remove numbers
Next

Range(Cells(8, 5), Cells(Rows.Count, 5).End(xlUp)).Value = valuesOfRangeToModify 

我的VB很老了所以它可能有语法错误,但你明白了。
这应该会给予巨大的推动。

作为参考,这里有一篇充满有趣建议的文章,有关上述解决方案的更多解释,请参阅第4点: http://www.soa.org/news-and-publications/newsletters/compact/2012/january/com-2012-iss42-roper.aspx

答案 3 :(得分:0)

也不要一次操作一个单元格。创建一系列单元格并将它们转换为数组进行处理。最后,阵列可用于替换单元格。

调整@mehow

的答案
Sub remove_numbers()
    Dim i As Long, N as Long, r as Range
    Set r = Range("B3") ' Whatever is the first cell in the column
    N = Range(r, r.End(xlDown)).Rows.Count 'Count the rows in the column
    Set r = r.Resize(N,1) ' Expand the range with all the cells
    Dim values() as Variant
    values = r.Value  ' Collect all the values from the sheet
    For i=1 to N
        values(i,1) = Split( values(i,1), "-")(1)
    Next i
    r.Value = values   'Replace values to the sheet
End Sub

为了使其更通用,您可以向过程添加一个参数,以将引用传递给列中的第一个单元格,如Sub remove_numbers(ByRef r as Range)。没有必要取消激活屏幕,因为最后只有一个写入操作,并且您希望屏幕在此之后更新。