简体   繁体   English

Excel VBA执行崩溃

[英]Excel vba executing crash

I have the following function to run on a large excel ark with 60k rows: 我具有以下功能,可在具有60k行的大型excel方舟上运行:

Private Sub mySub()
    Dim intRowA As Long
    Dim intRowB As Long

    Application.ScreenUpdating = False 

    Range("W1").EntireColumn.Insert

    For intRowA = 2 To ActiveSheet.UsedRange.Rows.Count
        If Cells(intRowA, 6).Value = "C" Then
            For intRowB = 2 To ActiveSheet.UsedRange.Rows.Count
                If Cells(intRowB, 6).Value = "P" Then
                    If Cells(intRowA, 4).Value = Cells(intRowB, 4).Value And Cells(intRowA, 7).Value = Cells(intRowB, 7).Value Then
                        Cells(intRowA, 23).Value = "Matched"
                        Cells(intRowB, 23).Value = "Matched"
                    End If
                End If
        DoEvents
            Next
        End If
    Next

    For intRowA = ActiveSheet.UsedRange.Rows.Count To 2 Step -1
        If Cells(intRowA, 23).Value <> "Matched" Then
            Rows(intRowA).Delete shift:=xlShiftUp
        End If
    Next

    Range("W1").EntireColumn.Delete

    Application.ScreenUpdating = True
End Sub

The idea to check where F columns are C and match them up with all F Rows that are value P Then at the end Delete all that does not match 检查F列在哪里C并将它们与所有FP匹配的想法,然后最后删除所有不匹配的行

The problem with this code as far as i can see is that it runs the 60k rows 60K times. 据我所知,此代码的问题是它运行60k行60k次。 which makes my script crash. 这使我的脚本崩溃了。 i am unsure how to improve it and thought that you guys might be able to see through this? 我不确定如何改善它,并认为你们也许可以看穿?

You're coming at this problem from the wrong direction - what makes a row distinct isn't whether column F has a 'C' or a 'P', it's whether the values in columns 'D' and 'G' match. 您从错误的方向上遇到了这个问题-使行与众不同的原因不是列F是否具有'C'或'P',而是列'D'和'G'中的值是否匹配。

The way to approach this is to collect 2 lists of rows with every distinct combination of 'D' and 'G' - one for rows with a 'C' in column F and one for rows with a 'P' in column F. Then, go through all of the distinct values for the 'C's and match based on the distinct combination. 解决此问题的方法是收集2个行列表,每个行都有“ D”和“ G”的每个不同组合-一个列F列中带有“ C”的行,一个列F列中带有“ P”的行。 ,检查“ C”的所有不同值,然后根据不同组合进行匹配。 Something like this (requires a reference to Microsoft Scripting Runtime): 这样的事情(需要对Microsoft脚本运行时的引用):

Private Sub mySub()

    Dim sheet As Worksheet
    Dim c_rows As Dictionary
    Dim p_rows As Dictionary

    Set sheet = ActiveSheet
    Set c_rows = New Dictionary
    Set p_rows = New Dictionary

    Dim current As Long
    Dim key As Variant
    'Collect all of the data based on keys of columns 'D' and 'G'
    For current = 2 To sheet.UsedRange.Rows.Count
        key = sheet.Cells(current, 4) & vbTab & sheet.Cells(current, 7)
        'Stuff the row in the appropriate dictionary based on column 'F'
        If sheet.Cells(current, 6).Value = "C" Then
            If Not c_rows.Exists(key) Then
                c_rows.Add key, New Collection
            End If
            c_rows.Item(key).Add current
        ElseIf sheet.Cells(current, 6).Value = "P" Then
            If Not p_rows.Exists(key) Then
                p_rows.Add key, New Collection
            End If
            p_rows.Item(key).Add current
        End If
    Next current

    sheet.Range("W1").EntireColumn.Insert

    'Now filter out the matching Ps that have keys in the C Dictionary:
    For Each key In c_rows.Keys
        If p_rows.Exists(key) Then
            Dim match As Variant
            For Each match In p_rows(key)
                sheet.Cells(match, 23).Value = "Matched"
            Next
        End If
    Next key

    For current = sheet.UsedRange.Rows.Count To 2 Step -1
        If sheet.Cells(current, 23).Value = "Matched" Then
            sheet.Rows(current).Delete xlShiftUp
        End If
    Next

    sheet.Range("W1").EntireColumn.Delete

End Sub

I agree it is the 60k x 60k loop causing the issue. 我同意这是造成问题的60k x 60k循环。 You can make the loop more efficient a few different ways: 您可以通过以下几种方法使循环更有效:

1) Run through the loop and delete all rows where column F doesn't equal C or P beforehand. 1)遍历循环,并删除列F不等于C或P的所有行。 This may solve the issue outright if there aren't that many rows that contain C or P. 如果没有太多包含C或P的行,这可能会彻底解决该问题。

2) Loop through all the rows once and store the necessary row numbers in an array or collection. 2)循环遍历所有行一次,并将必要的行号存储在数组或集合中。 Then do whatever you need done with the rows separately. 然后,单独处理行。 For example: 例如:

Dim intRow As Long
Dim cCollection As New Collection
Dim pCollection As New Collection

For intRow = 2 To ActiveSheet.UsedRange.Rows.Count
  If Cells(intRow, 6).Value = "C" Then
    cCollection.Add (intRow)
  ElseIf Cells(intRow, 6).Value = "P" Then
    pCollection.Add (intRow)
  End If
Next

Dim i As Integer
For i = 1 To cCollection.Count
  ' do something with cCollection(i)
Next

' multiple ways to loop through the collection...

Dim r As Variant
For Each r In pCollection
  'do something with pCollection(r)
Next r

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

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