Excel的优化

这里是情况:在我的Excel工作表中,我有一个列名为1-name的条目。 我想删除数字,考虑到这个数字也可以是两位数字。 这本身不是一个问题,我得到它的工作,只是performance是如此糟糕。 因为现在我的程序每个单元格需要大约半秒的时间。

我的问题:我该如何提高性能? 这里是代码:

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 

而不是使用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 

我的build议:

 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 

优化:

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

编辑:

正如@Mehow所build议的那样,您也可以使用一些性能

  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))

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

就像是 :

 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是相当老,所以它可能有语法错误,但你明白了。
这应该会有很大的提升。

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

也不要一次操作一个单元。 创build一个单元格的范围,并将其转移到数组进行处理。 最后,数组可以用来replace单元格。

调整@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) 。 不需要closures屏幕,因为最后只有一个写入操作,而您希望屏幕在此之后更新。