vba - 有没有办法在 IDE 而不是主机应用程序中显示用户表单?

标签 vba excel ide userform commandbar

我在 *.xlam 加载项中创建了一个用户表单,并在 IDE 中创建了一个新的命令栏和按钮,但是当我单击该按钮时,用户表单在 Excel 中打开,并且焦点被迫离开 IDE。有没有办法在 IDE 而不是主机应用程序中打开用户表单而不使用 .Net COM 插件?

这是创建命令栏和按钮并处理按钮单击事件的代码。

Option Explicit

Public WithEvents cmdBarEvents As VBIDE.CommandBarEvents

Private Sub Class_Initialize()
    CreateCommandBar
End Sub

Private Sub Class_Terminate()
    Application.VBE.CommandBars("VBIDE").Delete
End Sub

Private Sub CreateCommandBar()

    Dim bar As CommandBar
    Set bar = Application.VBE.CommandBars.Add("VBIDE", MsoBarPosition.msoBarFloating, False, True)
    bar.Visible = True

    Dim btn As CommandBarButton
    Set btn = bar.Controls.Add(msoControlButton, , , , True)
    btn.Caption = "Show Form"
    btn.OnAction = "ShowForm"
    btn.FaceId = 59

    Set cmdBarEvents = Application.VBE.Events.CommandBarEvents(btn)

End Sub

Private Sub cmdBarEvents_Click(ByVal CommandBarControl As Object, handled As Boolean, CancelDefault As Boolean)

    CallByName Me, CommandBarControl.OnAction, VbMethod

End Sub

Public Sub ShowForm()
    Dim frm As New UserForm1
    frm.Show
End Sub

附言您可能需要这行代码来删除命令栏...
Application.VBE.CommandBars("VBIDE").Delete

最佳答案

这是一个替代方案。

在您的用户表单上放置一个按钮。出于演示目的,我正在使用这个

enter image description here

接下来将此代码放入用户表单中

Private Sub CommandButton1_Click()
    Unload Me
    Application.Visible = True
End Sub

接下来将其粘贴到您的类(class)模块顶部
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Dim Ret As Long, ChildRet As Long

Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, _
ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, _
ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long

Private Const HWND_TOPMOST = -1
Private Const SWP_NOACTIVATE = &H10
Private Const SWP_SHOWWINDOW = &H40

最后更改您的Sub ShowForm()对此
Public Sub ShowForm()
    Dim frm As New UserForm1
    Dim Ret As Long

    frm.Show vbModeless

    Application.Visible = False

    Ret = FindWindow("ThunderDFrame", frm.Caption)

    SetWindowPos Ret, HWND_TOPMOST, 100, 100, 250, 200, _
    SWP_NOACTIVATE Or SWP_SHOWWINDOW
End Sub

这就是你得到的

enter image description here

编辑

更多的想法。为了防止用户在点击笑脸时创建更多的用户表单,更改 Sub ShowForm()到下面。 (替代方案是禁用笑脸并在表单卸载时重新启用它?)
Public Sub ShowForm()
    Dim frm As New UserForm1
    Dim Ret As Long
    Dim formCaption As String

    '~~> Set Userform Caption
    formCaption = "Blah Blah"

    On Error Resume Next
    Ret = FindWindow("ThunderDFrame", formCaption)
    On Error GoTo 0

    '~~> If already there in an instance then exit sub
    If Ret <> 0 Then Exit Sub

    frm.Show vbModeless
    frm.Caption = formCaption

    Application.Visible = False

    Ret = FindWindow("ThunderDFrame", frm.Caption)

    SetWindowPos Ret, HWND_TOPMOST, 100, 100, 250, 200, _
    SWP_NOACTIVATE Or SWP_SHOWWINDOW
End Sub

关于vba - 有没有办法在 IDE 而不是主机应用程序中显示用户表单?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26722253/

相关文章:

excel - 编译错误: Argument not optional error when I call macro from other macro

version-control - Intellij IDEA 红色/棕色突出显示的文件名

excel - 检查范围内的每个单元格是否有特定字符串?

VBA - 将字符串中的字符拆分、复制和粘贴到另一个单元格(有条件)

json - 使用 VBA 函数从 API 调用中提取结果

java - 实体 "uuml"已被引用,但未声明 - XMLStreamException

.net - Intellisense 无法检测 vb.net 创建的 dll 中的函数

java - 有没有办法在提交到 Git 之前强制执行 IntelliJ 代码样式格式?

c# - 我可以在 C++ 中创建一个类似于 C# 的全局命名空间层次结构来帮助开发人员使用我们的代码吗?

excel - 将列排序为八个单元格的行