gpt4 book ai didi

vba - 在运行时将用户窗体添加到不同的工作簿

转载 作者:行者123 更新时间:2023-12-02 01:43:30 25 4
gpt4 key购买 nike

我打开了一个插件和一个工作簿。该插件是一个 .xlam 文件,在工作簿中我添加了对它的引用。该插件受密码保护。

可以从我的工作簿中运行插件的公共(public)方法。但是,插件中的一种方法利用 VBA.UserForms.Add 打开在运行时创建的用户窗体 like this

假设包含对 myAddin 引用的工作簿具有以下内容:

Private Sub callAddin()
myAddin.ShowForm ThisWorkbook
End Sub

通常,我的插件中的代码如下所示:

Public Sub ShowForm(CallerWorkbook As Workbook)
Const vbext_ct_MSForm As Long = 3

'This is to stop screen flashing while creating form
Application.VBE.MainWindow.Visible = False

'Add to ThisWorkbook, not supplied workbook or VBE will crash - ignore CallerWorkbook
Dim myForm As Object
Set myForm = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm)

'Create the User Form
With myForm
.Properties("Caption") = "Select"
.Properties("Width") = 300
.Properties("Height") = 270
End With

'Show the form
Dim finalForm As Object
Set finalForm = VBA.UserForms.Add(myForm.Name)
finalForm.Show

'Remove form
ThisWorkbook.VBProject.VBComponents.Remove myForm

End Sub

效果很好。但是,当我的插件受密码保护时,不允许尝试向其中添加临时用户表单。没问题,我只需将临时用户窗体添加到调用代码的工作簿中,因为这不会受到密码保护

Sub ShowForm(CallerWorkbook As Workbook)
Const vbext_ct_MSForm As Long = 3

'This is to stop screen flashing while creating form
Application.VBE.MainWindow.Visible = False

'Add to CallerWorkbook instead
Dim myForm As Object
Set myForm = CallerWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm)

'Create the User Form
With myForm
.Properties("Caption") = "Select"
.Properties("Width") = 300
.Properties("Height") = 270
End With

'Show the form
Dim finalForm As Object
'Now myForm cannot be found and added
Set finalForm = VBA.UserForms.Add(myForm.Name)
finalForm.Show

'Remove form
CallerWorkbook.VBProject.VBComponents.Remove myForm

End Sub

但是,VBA 似乎无法看到 myForm.Name 现在指向的位置,因此 Add 方法失​​败,并显示“运行时错误 424:需要对象” “

有没有办法在另一个工作簿中显示运行时创建的表单?

最佳答案

您遇到的问题是用户窗体默认是私有(private)实例化的。这意味着一个项目无法引用另一个项目中的 UserForm,并且如果您无法引用该表单,则无法调用它的 Show 方法。

您的 Set myForm = CallerWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm) 语句返回 VbComponent,而不是 UserForm,这就是为什么然后您不能使用 VBA.UserForms.Add(myForm.Name)

有两种方法可以解决这个问题:

1 - 在加载项中创建一个 PublicNotCreatable 模板 UserForm

UserForm 就像一个类,因此它可以像类一样设置其Instancing 属性。但是,VBE 不会在用户窗体的属性窗口中公开 Instancing 属性,因此要设置实例,您需要导出表单,然后编辑 Attribute VB_Expose > 在再次导入表单之前,在文本编辑器中编辑 FRM 文件中的属性。步骤如下:

  • 在您的外接程序项目中创建一个名为 TemplateForm 的用户表单
  • 删除 TemplateForm 并选择在删除之前导出表单
  • 在文本编辑器中打开 TemplateForm.frm 文件
  • 编辑行Attribute VB_Expose = False,使其读取为Attribute VB_Exposed = True
  • 将更改保存到 TemplateForm.frm
  • TemplateForm.frm 导入您的加载项
  • 添加一个公共(public)函数,该函数将 TemplateForm 的新实例返回到您的外接程序。我已使此函数接受工作簿引用,以便加载项可以配置表单上的任何工作簿特定属性:

    Public Function GetTemplateForm(CallerWorkbook As Workbook) As TemplateForm
    Dim frm As TemplateForm
    Set frm = New TemplateForm
    'Set early-bound properties with intellisense
    frm.Caption = "Select"
    frm.Width = 300
    frm.Height = 270

    'Configure CallerWorkbook specific form properties here
    '...
    Set GetTemplateForm = frm
    End Function
  • 然后,您可以在用户的​​工作簿中显示 TemplateForm 的实例,而无需动态添加表单,或处理屏幕闪烁或难以调试的代码:

    Sub ShowAddinForm()
    With MyAddin.GetTemplateForm(ThisWorkbook)
    'Do more workbook specific propery setting here...
    '...
    .Show
    End With
    End Sub

** 注意 - Rubberduck VBA 插件很快就能添加 PublicNotCreatable 用户窗体。

2 - 让加载项创建 UserForm 组件,但让用户的工作簿管理它

这种方法不太优雅。用户需要管理更多代码,并且屏幕闪烁,并且难以调试代码。步骤如下:

  • 将此代码添加到加载项:

    Public Function GetTempFormName(CallerWorkbook As Workbook) As String
    Const vbext_ct_MSForm As Long = 3

    'This is to stop screen flashing while creating form
    Application.VBE.MainWindow.Visible = False

    'Add to CallerWorkbook instead
    With CallerWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm)
    .Properties("Caption") = "Select"
    .Properties("Width") = 300
    .Properties("Height") = 270
    GetTempFormName = .Name
    End With
    End Function

    Public Sub RemoveTempForm(CallerWorkbook As Workbook, FormName As String)
    With CallerWorkbook.VBProject.VBComponents
    Dim comp As Object
    Set comp = .Item(FormName)
    .Remove .Item(FormName)
    End With
    End Sub
  • 然后,在用户的工作簿中添加以下代码:

    Sub GetAddinToCreateForm()
    Dim FormName As String
    FormName = MyAddin.GetTempFormName(ThisWorkbook)
    With VBA.UserForms.Add(FormName)
    .Show
    End With
    MyAddin.RemoveTempForm ThisWorkbook, FormName
    End Sub

关于vba - 在运行时将用户窗体添加到不同的工作簿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51545083/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com