大循环在 VBA 中崩溃

Big loop crashes in VBA

截图

我正在用另一个列表 (1) 的频率排名更新单词列表 (2)。该代码旨在为列表 1 中的每个条目遍历列表 2,并将频率排名添加到其中的每个相同条目。如果我将列表限制为每个列表中的几个条目,它会完全按预期工作,但列表非常大。列表 1 包含 55.000 个单词,列表 2 包含 18.000 个单词。有没有办法防止代码崩溃,或者以更有效的方式重写代码?我确信它远非最佳,因为我是 VBA 的完全新手。我将粘贴下面的代码。

非常感谢

Option Explicit
Sub CorrectFrequencyData()

Dim Frequency As Double
Dim CurrentLocation As Range

Application.ScreenUpdating = False

Set CurrentLocation = Range("i5")

Do Until CurrentLocation.Value = ""

    Frequency = CurrentLocation.Offset(0, -6).Value
    Range("n4").Activate
    
    Do Until ActiveCell.Value = ""
    
        If ActiveCell.Value = CurrentLocation.Value Then ActiveCell.Offset(0, 1).Value = ActiveCell.Offset(0, 1).Value + Frequency
    
        ActiveCell.Offset(1, 0).Activate
    
    Loop
    
    Set CurrentLocation = CurrentLocation.Offset(1, 0)
    
Loop

Application.ScreenUpdating = True

End Sub

看起来可能有几种方法可以加速您的代码。首先,您可以使用 SUMIF,正如 GavinP 在您的第二个频率列中所建议的那样 =SUMIF(I:I, N4, C:C) 如果您将其向下流动到您的第二个频率列,这就是说检查第 I 列中 N + 行中的值以及在从 C 列到总计的频率处找到该值的所有地方。

现在可以选择加速您的代码:

Option Explicit
Sub CorrectFrequencyData()

Application.ScreenUpdating = False

我不确定您的代码中是否有公式,但您可以将它们设置为手动,而不是每次更改 sheet 上的值时都重新计算它们。

Application.Calculation = -4135 'xlCalculationManual

您可以将范围分配给一个数组,然后循环遍历速度更快的数组,而不是循环遍历您的 sheet。我们还可以消除为第一个列表中的每个条目遍历第二个列表的需要。我们将通过将第一个单词列表及其频率存储在字典中来做到这一点

Dim ArrWords() as variant
Dim LastRow as long

LastRow = ActiveSheet.Cells(ActiveSheet.Rows.Count, 9).End(-4162).Row  'Version non-specific Endrow, xlUP
ArrWords = Range("C4:I" & LastRow)

Dim dicWordFrequency as Object
Set dicWordFrequency = CreateObject("Dictionary.Scripting")

Dim tempWord as String

Dim i as Long
For i = 1 to Ubound(ArrWords)
    tempWord = arrWords(i,7)
    If not dicWordFrequency.Exists(tempWord) then
       DicWordFrequency.Add tempWord, arrWords(i,1)
    Else
       DicWordFrequency.Item(tempWord)= dicWordFrequency.Item(tempWord) + arrWords(i,1)
    End If
Next

现在我们可以遍历您的作品sheet并更新第二个列表中单词的频率。

LastRow = ActiveSheet.Cells(ActiveSheet.Rows.Count, 14).End(-4162).Row  'Version non-specific Endrow, xlUP
ArrWords = Range("N4:O" & LastRow)
For i = 1 to Ubound(arrWords)
    tempWord = arrwords(i,1)
    If dicWordFrequency.Exists(tempWord) then
        arrWords(i,2) = dicWordFrequency.Item(tempWord)
    End If
Next        

'Dump your new array with the totals to a range
Dim result as Range
Set Result = Range("N4")
Result.ReSize(UBound(arrWords,1), Ubound(ArrWords,2)).value = arrWords

Application.ScreenUpdating = True
Application.Calculation = -4105  'xlCalculationAutomatic

End Sub