运行macros时,variables数组“损坏” – Excel崩溃
我有一个macros(代码附加),将数据从两张表写入两个变种arrays。 然后使用嵌套循环在第一张表格中的第二张表格中查找所有可能的匹配。
当第一场比赛被发现一个变种arrays似乎被抹去,我得到一个'下标超出范围'。 这可能发生在数据被比较的时候,或者当我随后尝试从数组传递数据到另一个过程时,由于匹配被发现。
当我在Locals窗口中查看时,这个数组可以从显示存储值变为在每个索引中有错误消息“应用程序定义的或对象定义的错误”,或者根本没有索引,或者具有高负数的索引。
无论如何,如果我在代码处于debugging模式时尝试进一步调查,Excel崩溃(“Excel遇到问题,需要closures”)。
我已经按照这个链接的build议: http : //exceleratorbi.com.au/excel-keeps-crashing-check-your-vba-code/
…但无济于事。
我已经遍历代码,并可以跟踪第一次被testing的数据值是否匹配。 每次运行时,都会发生相同的索引(相同的i和j值)。
我在我们的办公室networking上使用Excel 2013。
任何人都可以告诉我什么可能导致这个或我可以执行的任何testing来帮助缩小原因?
难道是由于内存使用? arrays出来的时候大概是15000 x 11和4000 x 6,而小的是被破坏/失败的。
Sub classTest() Dim i As Long, j As Long Dim CK_Array() As Variant, RL_Array() As Variant Dim wb As Workbook Dim CK_Data As Worksheet, RL_Data As Worksheet Set wb = ThisWorkbook Set CK_Data = wb.Sheets(1) Set RL_Data = wb.Sheets(2) Call getRange_BuildArray(CK_Array, CK_Data) Call getRange_BuildArray(RL_Array, RL_Data) ' this sets the array that gets corrupted. For i = 2 To UBound(CK_Array) If Not IsEmpty(CK_Array(i, 6)) Then For j = 2 To UBound(RL_Array) If CK_Array(i, 6) = RL_Array(j, 4) Then ' array gets corrupted here or line below Call matchFound(dResults, CStr(CK_Array(i, 1) & " | " & CK_Array(i, 5)), CStr(RL_Array(j, 2) & " " & RL_Array(j, 3)), CStr(RL_Array(j, 1)), CStr(RL_Array(1, 3))) ' or array gets corrupted here End If Next j End If Next i End Sub Private Sub getRange_BuildArray(arr As Variant, ws As Worksheet) Dim endR As Long, endC As Long Dim rng As Range endR = ws.UsedRange.Rows.Count endC = ws.UsedRange.Columns.Count Set rng = Range(ws.Cells(1, 1), ws.Cells(endR, endC)) arr = rng End Sub
编辑:如这里所要求的是matchfound子代码。 这是一个字典,它保存集合中的类对象。 所以我也发布了下面的课程代码。 我还没有使用所有的类属性和方法,因为这个问题已经停止了我的testing。
Sub matchFound(dictionary As Object, nameCK As String, nameRL As String, RLID As String, dataitem As String) Dim cPeople As Collection Dim matchResult As CmatchPerson If dictionary.exists(nameCK) Then Set matchResult = New CmatchPerson matchResult.Name = nameRL matchResult.RLID = RLID matchResult.matchedOn = dataitem dictionary.Item(nameCK).Add matchResult Else Set cPeople = New Collection Set matchResult = New CmatchPerson matchResult.Name = nameRL matchResult.RLID = RLID matchResult.matchedOn = dataitem cPeople.Add matchResult dictionary.Add nameCK, cPeople End If End Sub
类
Option Explicit Private pName As String Private pRLID As String Private pMatchedOn As String Public Property Get Name() As String Name = pName End Property Public Property Let Name(Name As String) pName = Name End Property Public Property Get RLID() As String RLID = pRLID End Property Public Property Let RLID(ID As String) pRLID = ID End Property Public Property Get matchedOn() As String matchedOn = pMatchedOn End Property Public Property Let matchedOn(textString As String) pMatchedOn = textString End Property Public Sub MatchedOnString(datafield As String) Dim text As String text = Me.matchedOn & "|" & datafield Me.Name = text End Sub
我已经将您的问题简化为最小化,可validation和完整的示例。
将范围的隐式默认值分配给作为Variant数组传递的Variantvariables时,会发生此问题。
Sub VariantArrayWTF() Dim aBar() As Variant Dim aFoo() As Variant GetArray aBar GetArray aFoo Debug.Print aBar(1, 1) 'aFoo() has now lost it's `+` sign in Locals window, but the bounds are still visible Debug.Print aBar(1, 1) 'aFoo() has now lost its bounds in Locals Window 'aFoo(1,1) will produce subscript out of range 'Exploring the Locals Window, incpsecting variables, will crash Excel Debug.Print aFoo(1, 1) End Sub Sub GetArray(ByRef theArray As Variant) 'Note the use of theArray instead of theArray() 'Implicitly calling the default member is problematic theArray = Sheet1.UsedRange End Sub
有一些解决方法 – 我build议使用两个 :
使用显式调用`Range.Value`
你甚至可以直接调用默认的成员Range.[_Default]
。 确切的方法并不重要,但必须明确。
Sub GetArray(ByRef theArray As Variant) theArray = Sheet1.UsedRange.Value End Sub
避免使用“调用”,并传递通用的变体定义
-
Call
是一个不赞成的声明,可以省略。 - 一致地声明数组和辅助函数的数组参数。 也就是说,在所有的情况下使用(),或者没有。
注意声明Dim aFoo() As Variant
是一个Dim aFoo() As Variant
types的数组,并声明Dim aFoo As Variant
是一个Varianttypes,它可以包含一个数组。
与括号
Sub VariantArrayWTF() Dim aBar() As Variant Dim aFoo() As Variant GetArray aBar GetArray aFoo Debug.Print aBar(1, 1) Debug.Print aBar(1, 1) Debug.Print aFoo(1, 1) End Sub Sub GetArray(ByRef theArray() As Variant) theArray = Sheet1.UsedRange End Sub
没有括号
Sub VariantArrayWTF() Dim aBar As Variant Dim aFoo As Variant GetArray aBar GetArray aFoo Debug.Print aBar(1, 1) Debug.Print aBar(1, 1) Debug.Print aFoo(1, 1) End Sub Sub GetArray(ByRef theArray As Variant) theArray = Sheet1.UsedRange End Sub
我find了导致问题的代码行。 然而,我不能解释为什么它一定会导致崩溃,所以我将不胜感激为什么发生这种情况的其他投入。
将RL和CK数组传递给getRange_Build数组时,我忽略了将这些variables表示为数组的括号。
代码是这个…
Call getRange_BuildArray(CK_Array, CK_Data) Call getRange_BuildArray(RL_Array, RL_Data)
…但应该是这个
Call getRange_BuildArray(CK_Array(), CK_Data) Call getRange_BuildArray(RL_Array(), RL_Data)
我想这是因为没有被标记为编译错误的原因是因为在getRange_BuildArray过程本身的问题参数也缺乏必要的括号来表示一个数组。
这是…
Private Sub getRange_BuildArray(arr As Variant, ws As Worksheet)
应该是这个
Private Sub getRange_BuildArray(arr() As Variant, ws As Worksheet)
随着这些变化,macros已成功完成整个数据集,并不会导致Excel崩溃。
如前所述,如果有人能提供一个更详细的细节分析如何导致excel崩溃,那将是非常好的。