Excel VBA用户窗体QueryClose:取消不起作用

3
我已经编写了下面的代码,以便在关闭表单之前检查进程是否已完成。此用户窗体用作成绩单,将在子程序的最后一步中使range("A6")变为绿色以表示通过,或使range("B6")变为红色以表示失败,然后卸载表单。
从我到目前为止在网上检查的内容来看,它应该可以工作。调试时,宏一直运行到 Cancel = True 的位置,并读取该行,但表单仍然关闭。
为什么即使读取该行,取消也没有被注册?
Private Sub Userform_queryclose(CloseMode As Integer, Cancel As Integer)
Dim wbScoreCard As Workbook
Dim wsScoreCard As Worksheet
Dim MSG As String
Set wbScoreCard = Workbooks(NameBox.Value)
Set wsScoreCard = wbScoreCard.Worksheets(Format(Date, "MM.dd.yy") & " " & CallType.Caption)
If Err.Number = 0 Then
    If wsScoreCard.Range("A6").Interior.Color <> vbGreen Then
        If wsScoreCard.Range("B6").Interior.Color <> vbRed Then
            Beep
            MSG = MsgBox("This scorecard is not complete! If you close it now, this scorecard will not be saved. Continue?", vbYesNo, "Warning - Scorecard Incomplete")
            If MSG = vbYes Then
                wbScoreCard.Close savechanges:=False
                Exit Sub
            Else
                Cancel = True
                Exit Sub
            End If
        End If
    End If
End If
End Sub

为什么 Cancel 是一个整数,而最终你将其设置为 true(1)?Cancel 在做什么? - BruceWayne
1个回答

6

几件事情:

  • You're not shutting off error handling, so the Err.Number = 0 check has no effect; if there's a runtime error, execution jumps straight out of the procedure anyway.

  • MSG should be a vbMsgBoxResult, not a String. Your code only works because of implicit type conversions from the underlying Integer value to the String type you're forcing it into.

  • Unless you didn't post your entire code, Exit Sub is redundant in both branches.

  • The problem can be reproduced with simpler code:

    Private Sub Userform_queryclose(CloseMode As Integer, Cancel As Integer)
        Cancel = True
    End Sub
    
问题在于您编造了这个签名或者从记忆中输入了它。这是QueryClose处理程序的签名:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
请注意参数的顺序。将您的CloseMode设置为True而不是Cancel,即可获得预期的行为...但更好的解决方法是按正确的顺序放置参数。
事件处理程序实际上并不关心参数名称:它关心类型和顺序。由于两个参数都是整数,因此取决于顺序:第一个整数参数被解释为Cancel参数,第二个是CloseMode——表单/COM不关心您如何调用它们,它将从第一个参数读取Cancel值。
您可以通过在代码窗格顶部的下拉菜单中选择事件来避免这个问题。

first select the UserForm interface/event provider from the left dropdown

确保左侧下拉菜单显示为“UserForm”,然后从右侧下拉菜单中选择“QueryClose”:

then select QueryClose event in the right dropdown

如果没有处理程序,VBE将会为您创建一个格式正确的处理程序。

1
谢谢提供的信息,问题已经解决了。1 - 实际上,在子程序的底部我删除了一些错误处理代码,这就是为什么我使用了err.number。我只是觉得它对这部分没有用。既然我删除了底部的代码,我应该先把那个if语句删掉。退出子程序的部分也是出于同样的原因。2 - 我一直将MSG定义为字符串,真有趣,我这么长时间以来都弄错了... 3 - 我肯定是凭记忆输入的:以后再也不会这样了...总之,非常感谢你简明扼要且详细的回答!我给你点赞了 :) - Jared Burton
1
@JaredBurton 感谢您的勾选!如果您有可用的 VBA 代码需要同行审查,我很乐意在 [codereview.se] 上看到一些。 =) - Mathieu Guindon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接