[英]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并将它们与所有F
值P
匹配的想法,然后最后删除所有不匹配的行
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.