更新:
我的PC上的Visio和Excel似乎没有使用相同的Office对象库,至少这是使用的引用告诉我的。 Visio使用15.0,Excel使用16.0,我们为两者使用不同的订阅,Excel是MS Office 365 ProPlus软件包的一部分,Visio是单独的。
我在带有16.0 Office对象库的当前Visio订阅的PC上对其进行了测试。这次关闭Userform不会导致崩溃。所以我想问题出在旧版本上。如果有人能够交叉检查并在Excel 15.0安装中测试代码,那就太好了。
原始帖子
我一直在VBA中使用观察者实现来创建一些实现界面的“更好”的用户窗体。
就我而言,该解决方案效果很好,但是有一个小问题:
每当我通过按下FormControlMenu Close控件(右上角的红色X)关闭UserForm时,我的应用程序就会崩溃,并显示“ Out of Stack Space Error”。
崩溃以下列方式发生:我收到带有错误(标准VBA)的消息框,当我关闭它时似乎没有任何毛病,但是一旦我尝试运行另一段代码(任何),Visio就会崩溃到桌面。
现在奇怪的部分:我实际上捕获了vbQueryClose事件,将其取消并运行自己的关闭例程,该例程仅隐藏用户窗体。当以相同的方式(me.hide)通过commandButton关闭(隐藏)UserForm时,不会发生错误。
这仅在Visio中发生,完全相同的代码在Excel中不会导致错误/崩溃!
我希望对参考/对象/ COM-Business有更多了解的人可以对此有所了解
代码:
代码也可以作为压缩文件使用(没有Excel / Visio文件,只有导出的模块),因此您不必复制/粘贴和创建用户窗体:https://www.dropbox.com/s/ziqjv2umcy3co5t/ObserverExample.zip?dl=0
实际的Observer实施要长一些,但是此代码是最小的可验证示例。
模块1(模块):
'@Folder("ObserverTest")
Option Explicit
Sub StartTest()
With New Foo
.Test
End With
End Sub
Foo(类):
'@Folder("ObserverTest")
Option Explicit
Private WithEvents myObs As Observer
Private myView As IBar
Public Sub Test()
Set myView = New Bar
Dim myViewAsObservable As IObservable
Set myViewAsObservable = myView
myViewAsObservable.AddObserver myObs
Set myViewAsObservable = Nothing
myView.Show
Debug.Print myView.howClosed
End Sub
Private Sub Class_Initialize()
Set myObs = New Observer
End Sub
Private Sub Class_Terminate()
Set myObs = Nothing
End Sub
Private Sub myObs_Notify(source As Object, arg As Variant)
If VarType(arg) = vbString Then
Debug.Print arg
End If
End Sub
IBar(类)
'@Folder("ObserverTest")
Option Explicit
Public Sub Show(): End Sub
Public Property Get howClosed() As String: End Property
IObservable(类)
'@Folder("ObserverTest")
Option Explicit
Public Sub AddObserver(ByVal obs As Observer): End Sub
条形图(用户窗体)
'@Folder("ObserverTest")
Option Explicit
Implements IBar
Implements IObservable
Private obsCol As Collection
Private cancelHow As String
'---IBar Stuff
Private Sub IBar_Show()
Me.Show
End Sub
Private Property Get IBar_howClosed() As String
IBar_howClosed = cancelHow
End Property
'--- Closing Stuff
Private Sub btCancel_Click()
cancelHow = "Closed by pressing the >Cancel< Button"
onCancel
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = VbQueryClose.vbFormControlMenu Then
Cancel = True
cancelHow = "Closed by pressing the >X< Control"
onCancel
End If
End Sub
Private Sub onCancel()
Me.hide
End Sub
'---Observer Stuff
Private Sub UserForm_Initialize()
Set obsCol = New Collection
End Sub
Private Sub UserForm_Terminate()
Set obsCol = Nothing
End Sub
Private Sub tbTest_Change()
Notify Me.tbTest.Text
End Sub
Private Sub IObservable_AddObserver(ByVal obs As Observer)
obsCol.Add obs
End Sub
Private Sub Notify(ByVal arg As Variant)
Dim obs As Observer
For Each obs In obsCol
obs.Notify Me, arg
Next obs
End Sub
观察员(类)
'@Folder("ObserverTest")
Option Explicit
Public Event Notify(source As Object, arg As Variant)
Public Sub Notify(ByVal source As Object, ByVal arg As Variant)
RaiseEvent Notify(source, arg)
End Sub
最佳答案
问题显然出在我使用的Office对象库的版本上。使用16.0(2016)库而不是15.0(2013)为我解决了这个问题。
如果有人有很好的解释,请将其张贴在此处,我将接受它作为答复。
关于excel - 观察者模式:通过FormControl关闭UserForm导致堆栈空间不足错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57337692/