2

情况如下:在我的 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

4 回答 4

4

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

试试下面的代码

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
于 2013-09-17T07:10:39.877 回答
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))

于 2013-09-17T09:29:10.543 回答
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

于 2013-09-17T07:18:22.177 回答
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). 无需停用屏幕,因为最后只有一次写入操作,并且您希望屏幕在此之后更新。

于 2013-09-17T14:04:27.007 回答