Excel VBA启动Userforms无模式,然后转到模式

Excel VBA启动Userforms无模式,然后转到模式,excel,modal-dialog,userform,modeless,Excel,Modal Dialog,Userform,Modeless,Excel允许从无模式表单开始,然后显示模式表单(但不是相反) 我有一个带有4个用户表单的应用程序:UF1-选择合作伙伴,UF2-列出现有交易,UF21-显示现有交易,UF22-创建新交易。UF21和UF22都源于UF2 UF21需要非模态,以便显示多个事务并并行比较,因此UF1、UF2和UF21都是非模态的。但我希望UF22是模态的,以便一次发布一个新事务 我的问题是,在我关闭UF22之后,即使只是从表格中一下子逃出,所有以前的表格都会关闭。我应该可以回到UF2。如果我把UF22做成非模态的,

Excel允许从无模式表单开始,然后显示模式表单(但不是相反)

我有一个带有4个用户表单的应用程序:UF1-选择合作伙伴,UF2-列出现有交易,UF21-显示现有交易,UF22-创建新交易。UF21和UF22都源于UF2

UF21需要非模态,以便显示多个事务并并行比较,因此UF1、UF2和UF21都是非模态的。但我希望UF22是模态的,以便一次发布一个新事务

我的问题是,在我关闭UF22之后,即使只是从表格中一下子逃出,所有以前的表格都会关闭。我应该可以回到UF2。如果我把UF22做成非模态的,一切都好

我已经编写了一个遍历UserForms集合的函数,并且能够获得对要激活的表单对象的引用。因此,我能够返回(在调试模式下)到UF2,它是一个列表框,激活列表框,但是在最后一个挂起的语句之后,UF2和UF1都关闭了

由于模态和非模态形式的性质,我试图做的是不可能的,还是我应该继续推动正确的代码

由于我最初的问题仍然悬而未决,并且@PeterT提出的解决方案的测试实现无法正常工作,因此我根据@PeterT的建议,加入了我目前拥有的代码

'===============
' Form UF1
'===============

Private Sub UserForm_Activate()

If ActivateUF22(FormID) = True Then Exit Sub

'.... more commands

End Sub

'============
' Form UF2
'============

Private Sub UserForm_Activate()

If ActivateUF22(FormID) = True Then Exit Sub

'.... more commands

End Sub

'----------------

Private Sub Cbn_OpenUF22_Click()

If ActivateUF22() = True Then
    Exit Sub
Else
    With New UF22
        .Show vbModeless
    End With
End If

End Sub

'================
' In a Module...
'================

Public Function ActivateUF22() As Boolean

Dim frm As Object

Set frm = GetFormFromID("UF22*") ' Custom function to get a form Object based on
                                 ' some criterion (FormID in a hidden TextBox)
If Not frm Is Nothing Then
    ' the only way I know to *Activate* an already .Show(n) form and compensate 
    ' for the fact that the Close CommandButton may already have Focus
    frm.TBx_UF22_CODE.SetFocus
    frm.CBn_UF22_CLOSE.SetFocus
    ActivateUF22 = True
Else
    ActivateUF22 = False
End If

End Function

嗯,我终于设法找到了解决办法

剩下的问题是,在同一个userform上单击两次,除了“Modal”一次之外,还会成功并允许用户跳出

我甚至尝试了在另一个SO线程中找到的“AppActivate Application.caption”方法,但也不起作用

唯一有效且不会困扰我的解决方案是插入一个带有警告的MsgBox,如下所示:

Public Function ActivateUF22() As Boolean

Dim frm As Object

Set frm = GetFormFromID("UF22*") ' Custom function to get a form Object based on
                                 ' some criterion (FormID in a hidden TextBox)
If Not frm Is Nothing Then
    ' the only way I know to *Activate* an already .Show(n) form and compensate 
    ' for the fact that the Close CommandButton may already have Focus
    frm.TBx_UF22_CODE.SetFocus
    frm.CBn_UF22_CLOSE.SetFocus
    ActivateUF22 = True
在内部显示MsgBox可以实现这一功能,将焦点切换到与单击的焦点不同的形式,并在返回时切换到UserForm。Activate事件正常激发,ActivateUF22函数可防止用户转义伪模态形式

谢谢@PeterT为我指出了一个解决方法。我设法做到了我开始要做的事情,尽管方式不同


PS我仍然相信有一种方法可以从非模态形式转换为模态形式。毕竟,我使用的MsgBox显然是一种模态形式,它的工作方式与我所希望的一样;-)

我会在您的UF21表单中设置一个标志,指示UF22处于打开状态(且无模式)。如果用户试图与UF21交互,请检查标志,如果它显示UF22已打开,您可以“闪烁”UF21,作为用户应填写UF22表单的指示。很抱歉@PeterT,显然我没有明确说明UF21和UF22都由UF2显示。无论如何,我明白你的意思,使用UF22进行无模式化,并检查是否有任何其他表单被激活,以阻止激活并返回UF22,从而有效地实现模式行为。我已经有了检查Userforms集合的机制,因此很容易找到UF22是否处于活动状态。但我不确定终止过程中会发生什么。i、 e.UF2是否会在UF22终止后或之前运行签入激活事件。“我会让你知道的。”皮特,这就像我害怕的一样。如果我点击UF1,例行程序就会工作,并再次“激活”UF22。UF2也一样。如果我按顺序单击UF1-UF2-UF1-UF2等也一样。但是如果我连续两次单击同一表单,激活甚至不会启动,因此例程不会启动。就好像焦点仍然在UF1(或者UF2)上,即使活动窗口(根据操作系统的活动窗口颜色判断)是UF22。您能告诉我如何按需激活表单吗?我找到的唯一方法是将焦点设置为表单上的某个命令按钮或文本框。
MsgBox("You cannot move away from this form until it is either completed or cancelled")
Else
    ActivateUF22 = False
End If

End Function