Excel 输入左括号时崩溃
Excel crash when typing open parenthesis
这是一个我不明白的。
给定这个 class 模块(精简到重现崩溃所需的最低限度):
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "TestCrashClass"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Public Function Init() As TestCrashClass
Attribute Init.VB_UserMemId = 0
Dim tcc As New TestCrashClass
Set Init = tcc
End Function
Public Property Get Data() As String
Data = "test data"
End Property
谁能告诉我为什么 Excel 在我输入这段代码时完全乱码:
Sub MakeExcelCrash()
With TestCrashClass(
在这一点上,我这个可爱的消息:
即使我输入了一个没有括号的完整过程,然后尝试稍后添加它们,我也会遇到同样的崩溃。
让我 Excel 不崩溃的唯一方法是 copy/paste 从其他地方到这行代码的一组 ()
。
Sub MakeExcelCrash()
With TestCrashClass()
Debug.Print .Data
End With
End Sub
如果 Init()
方法有一个参数——即使是一个可选参数——它在输入左括号时也不会崩溃。
我更好奇为什么会发生这种情况,而不是解决它的方法;它实际上并没有经常出现在我的代码中,当它出现时我可以通过改变方法来修复它,但我真的很沮丧,因为我不知道是什么导致了这些崩溃。所以也许对 VBA 的内部工作了解更多的人可以向我解释一下?
听起来像是某种腐败。我以前有过 Excel 像这样的非理性行为,通常是在大型项目中,解决它的唯一方法是将所有 类 等拖到一个新项目中。
我怀疑这是因为 Excel 没有真正删除 类、模块、工作表等已删除的内容。由于文件大小,您可以看出这一点。
据我所知,Access 中没有压缩和修复功能
正如@TimWilliams 指出的那样,有一个默认成员 returns same class(或 class 循环的一个实例例如 ParentClass.ChildClass.ParentClass.ChildClass...
其中 ParentClass 和 ChildClass 都有默认成员),并且在某些语法情况下使用时,例如 With
块,将导致 VBE 尝试解析默认成员。
第一个括号使 VBE 假设必须有一个方法,索引为 get
或数组索引,它将接受一个参数,因此它开始解析最终目标成员。
因此 不完整 行,光标位于括号后:
With TestCrashClass(
实际上等同于:
With TestCrashClass.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init '....You're inquisitive scrolling this far over, but you get the point.
在某些时候,您的系统或 VBE 会耗尽资源并以热核 group-hug 的优雅和镇定退出。
+1 即兴创作一对括号 copy/pasta。
您甚至不需要 With
块。 任何 尝试在 class 名称取下 Excel 后键入 (
。
问题是您将 VB_PredeclaredId
设置为 true,而默认成员正在尝试 return 本身。当您将调试器附加到垂死的 Excel 实例时,您可以看到根本问题是堆栈溢出:
Unhandled exception at 0x0F06EC84 (VBE7.DLL) in EXCEL.EXE: 0xC00000FD:
Stack overflow (parameters: 0x00000001, 0x00212FFC).
当您键入 With TestCrashClass(
时,VBA 开始在 indexer默认 属性,因为 Init()
没有任何属性。例如,考虑 Collection
。您可以像这样使用默认的 属性 的 (Item
) 索引器:
Dim x As Collection
Set x = New Collection
x.Add 42
Debug.Print x(1) '<--indexed access via default member.
这完全等同于Debug.Print x.Items(1)
。这是您开始 运行 遇到问题的地方。 Init()
没有参数,因此 VBA 开始向下钻取默认成员以找到第一个具有索引器的成员,以便 IntelliSense 可以显示参数列表。它开始这样做:
x.[default].[default].[default].[default].[default]...
在你的例子中,它创建了一个无限循环,因为 [default]
returns x
。同样的事情发生在上面的 Collection
代码中(除了它找到一个):
加上你有一个默认实例,最终结果是这样的:
Private Sub Class_Initialize()
Class_Initialize
End Sub
这是一个我不明白的。
给定这个 class 模块(精简到重现崩溃所需的最低限度):
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "TestCrashClass"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
Public Function Init() As TestCrashClass
Attribute Init.VB_UserMemId = 0
Dim tcc As New TestCrashClass
Set Init = tcc
End Function
Public Property Get Data() As String
Data = "test data"
End Property
谁能告诉我为什么 Excel 在我输入这段代码时完全乱码:
Sub MakeExcelCrash()
With TestCrashClass(
在这一点上,我这个可爱的消息:
即使我输入了一个没有括号的完整过程,然后尝试稍后添加它们,我也会遇到同样的崩溃。
让我 Excel 不崩溃的唯一方法是 copy/paste 从其他地方到这行代码的一组 ()
。
Sub MakeExcelCrash()
With TestCrashClass()
Debug.Print .Data
End With
End Sub
如果 Init()
方法有一个参数——即使是一个可选参数——它在输入左括号时也不会崩溃。
我更好奇为什么会发生这种情况,而不是解决它的方法;它实际上并没有经常出现在我的代码中,当它出现时我可以通过改变方法来修复它,但我真的很沮丧,因为我不知道是什么导致了这些崩溃。所以也许对 VBA 的内部工作了解更多的人可以向我解释一下?
听起来像是某种腐败。我以前有过 Excel 像这样的非理性行为,通常是在大型项目中,解决它的唯一方法是将所有 类 等拖到一个新项目中。
我怀疑这是因为 Excel 没有真正删除 类、模块、工作表等已删除的内容。由于文件大小,您可以看出这一点。
据我所知,Access 中没有压缩和修复功能
正如@TimWilliams 指出的那样,有一个默认成员 returns same class(或 class 循环的一个实例例如 ParentClass.ChildClass.ParentClass.ChildClass...
其中 ParentClass 和 ChildClass 都有默认成员),并且在某些语法情况下使用时,例如 With
块,将导致 VBE 尝试解析默认成员。
第一个括号使 VBE 假设必须有一个方法,索引为 get
或数组索引,它将接受一个参数,因此它开始解析最终目标成员。
因此 不完整 行,光标位于括号后:
With TestCrashClass(
实际上等同于:
With TestCrashClass.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init.Init '....You're inquisitive scrolling this far over, but you get the point.
在某些时候,您的系统或 VBE 会耗尽资源并以热核 group-hug 的优雅和镇定退出。
+1 即兴创作一对括号 copy/pasta。
您甚至不需要 With
块。 任何 尝试在 class 名称取下 Excel 后键入 (
。
问题是您将 VB_PredeclaredId
设置为 true,而默认成员正在尝试 return 本身。当您将调试器附加到垂死的 Excel 实例时,您可以看到根本问题是堆栈溢出:
Unhandled exception at 0x0F06EC84 (VBE7.DLL) in EXCEL.EXE: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x00212FFC).
当您键入 With TestCrashClass(
时,VBA 开始在 indexer默认 属性,因为 Init()
没有任何属性。例如,考虑 Collection
。您可以像这样使用默认的 属性 的 (Item
) 索引器:
Dim x As Collection
Set x = New Collection
x.Add 42
Debug.Print x(1) '<--indexed access via default member.
这完全等同于Debug.Print x.Items(1)
。这是您开始 运行 遇到问题的地方。 Init()
没有参数,因此 VBA 开始向下钻取默认成员以找到第一个具有索引器的成员,以便 IntelliSense 可以显示参数列表。它开始这样做:
x.[default].[default].[default].[default].[default]...
在你的例子中,它创建了一个无限循环,因为 [default]
returns x
。同样的事情发生在上面的 Collection
代码中(除了它找到一个):
加上你有一个默认实例,最终结果是这样的:
Private Sub Class_Initialize()
Class_Initialize
End Sub