更新:

我的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/

10-09 08:34
查看更多