简体   繁体   English

VBA代码运行两个循环非常慢

[英]VBA code runs two loops very slow

I have this code which runs two loops after each other. 我有这段代码,它们彼此之后运行两个循环。 It works fine for a few thousand rows. 它适用于数千行。 But as the number of rows increases, the code runs significantly longer. 但是随着行数的增加,代码的运行时间将大大延长。 It should loop over 100.000 rows but this will take hours and hours. 它应该循环超过100.000行,但这将需要几个小时。 Please let me know if you see a reason why this code is taking so long 如果您看到此代码花了这么长时间的原因,请告诉我

Sub BSIS()

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual


Dim lngRow As Long
Dim counter As Long

       'Merge rows with duplicate Cells

With ActiveSheet

.Cells(1).CurrentRegion.Sort key1:=.Cells(1), Header:=xlYes 'change this to xlYes if your table has header cells

  For lngRow = ActiveSheet.UsedRange.Rows.Count To 2 Step -1

    If ActiveSheet.Cells(lngRow - 1, 1) = ActiveSheet.Cells(lngRow, 1) Then
        .Cells(lngRow - 1, 4) = .Cells(lngRow - 1, 4) + .Cells(lngRow, 4)
        .Rows(lngRow).Delete
    End If
  Next lngRow

End With

        'Delete rows with negative cells


With ActiveSheet

  For counter = ActiveSheet.UsedRange.Rows.Count To 1 Step -1

     If ActiveSheet.Cells(counter, 4) <= 0 Then
        .Rows(counter).Delete
     End If

  Next counter

End With

Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True

End Sub

one option would be copying the range of data you want to examine into an array. 一种选择是将要检查的数据范围复制到数组中。 Do what ever data processing you want with that array, then copy the results back into the excel sheet. 使用该数组进行所需的数据处理,然后将结果复制回excel工作表。 Here is an example: 这是一个例子:

Dim i As Integer
Dim j As Integer
Dim flagMatch As Boolean
Dim arrData2Search As Variant


Set arrData2Search = Range(Cells(1, 1), Cells(1000, 2000)).value

flagMatch = False
For j = 1 To 1000
    For i = 1 To 2000
        If arrData2Search (i, j)= "Target" Then
             flagMatch = True
        End If
    Next i
Next j

The reason for slow run is that you are deleting rows one by one . 运行缓慢的原因是要逐行删除行

It always better to do it in single shot using UNION function 使用UNION功能单拍总是更好

Try the below code it should work,(Tested) 尝试下面的代码,它应该工作,(已测试)

Dim uni As Range

With ActiveSheet

    .Cells(1).CurrentRegion.Sort key1:=.Cells(1), Header:=xlYes

    For lngRow = ActiveSheet.UsedRange.Rows.Count To 2 Step -1

        If ActiveSheet.Cells(lngRow - 1, 1) = ActiveSheet.Cells(lngRow, 1) Then

            .Cells(lngRow - 1, 4) = .Cells(lngRow - 1, 4) + .Cells(lngRow, 4)
            If Not uni Is Nothing Then
                Set uni = Application.Union(uni, Range(.Rows(lngRow).Address))
            Else
                Set uni = Range(.Rows(lngRow).Address)
            End If

        End If
    Next lngRow

    uni.Delete

End With

There are a number of ways to optimize performance of one's VBA code, and a good number of articles and forums have covered the topic. 有很多方法可以优化一个人的VBA代码的性能,并且有很多文章和论坛都介绍了该主题。 For a great resource, see this . 要获取大量资源, 请参见this

One of the main things to remember is that every time your code interacts with the UI of Excel, it uses much more overhead than if the interaction had not occurred. 要记住的主要事情之一是,每次您的代码与Excel的UI进行交互时,与未进行交互时相比,它会消耗更多的开销。 That's why (to VBA Programmer's point) it's much faster to load the data to an array, perform your calculations, and then write the array back to a sheet. 这就是为什么(就VBA程序员而言)将数据加载到数组,执行计算然后将数组写回到工作表要快得多。 And that's why (to Sathish's point) it's much faster to delete all the rows at once (one interaction) compared to each one individually (multiple interactions). 这就是为什么(就Sathish而言),一次删除所有行(一次交互)要比单独删除每行(多次交互)要快得多。 For more information about deleting rows, see this . 有关删除行的更多信息, 请参见this

With regards to your code, is there any particular reason you need two loops? 关于您的代码,是否有任何特定原因需要两个循环?

Untested 未经测试

Sub BSIS()

Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual

Dim lngRow As Long
Dim r As Range

With ActiveSheet
    .Cells(1).CurrentRegion.Sort key1:=.Cells(1), HEADER:=xlYes 'change this to xlYes if your table has header cells
    'One loop:
    For lngRow = .UsedRange.Rows.Count To 2 Step -1

        'Merge rows with duplicate Cells
        If .Cells(lngRow - 1, 1) = .Cells(lngRow, 1) Then
            .Cells(lngRow - 1, 4) = .Cells(lngRow - 1, 4) + .Cells(lngRow, 4)
            If r Is Nothing Then
                Set r = .Cells(lgnrow, 1)
            Else: Set r = Union(r, .Cells(lgnrow, 1))
        End If

        'Delete rows with negative cells
        If .Cells(lngRow, 4) <= 0 Then
            If r Is Nothing Then
                Set r = .Cells(lngRow, 1)
            Else: Set r = Union(r, .Cells(lgnrow, 1))
        End If

    Next lngRow
End With

'Delete rows
r.EntireRow.Delete

Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True

End Sub

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM