Добавление userform в другую книгу во время выполнения
у меня есть addin и открытая книга. В addin это .файл xlam и в книге я добавил ссылку на него. Этот файл защищен паролем.
можно запустить общедоступные методы добавления из моей книги. Однако один метод в addin использует VBA.UserForms.Add
чтобы открыть пользовательскую форму, созданную во время выполнения такой
скажем, книга, которая содержит ссылку на myAddin
это:
Private Sub callAddin()
myAddin.ShowForm ThisWorkbook
End Sub
обычно, код в моем addin выглядит так:
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
который отлично работает. Однако, когда мой addin защищен паролем, попытка добавить временную пользовательскую форму к нему не разрешена. Нет проблем, я просто добавляю временную форму пользователя в книгу, которая вызвала код, так как это не будет защищено паролем
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
указывает на now, поэтому метод Add не работает с "Run time error 424: Object required"
есть ли способ открыть форму созданного во время выполнения в другой книге?
1 ответов
проблема, с которой вы сталкиваетесь, заключается в том, что по умолчанию пользовательские формы создаются частным образом. Это означает, что проект не может ссылаться на пользовательскую форму в другом проекте, а если вы не можете ссылаться на форму, вы не можете вызвать ее Show
метод.
код Set myForm = CallerWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm)
оператор возвращает VbComponent
, а не UserForm
, поэтому вы не можете использовать VBA.UserForms.Add(myForm.Name)
есть 2 способа обойти это:
1 - Создать PublicNotCreatable
шаблон UserForm в вашем добавить-в
пользовательская форма похожа на класс, поэтому она может иметь свой Instancing
набор свойств, как и класс. Однако VBE не выставляет Instancing
свойство в окне Свойства для UserForms, поэтому для установки экземпляра необходимо экспортировать форму, а затем отредактировать Attribute VB_Exposed
атрибут в файле FRM в текстовом редакторе перед повторным импортом формы. Вот шаги:
- создайте пользовательскую форму с именем
TemplateForm
надстройки проект - удалить
TemplateForm
и выберите Экспорт формы перед ее удалением - открыть
TemplateForm.frm
файл в текстовом редакторе - изменить строку
Attribute VB_Exposed = False
так вот читаетAttribute VB_Exposed = True
- сохраните изменения в
TemplateForm.frm
- импорт
TemplateForm.frm
в надстройке -
добавить публичную функцию, которая возвращает новый экземпляр
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
UserForm.
2 - есть надстройка создать пользовательскую форму компонент, но пусть книга пользователя управляет им
этот подход не так элегантен. Там гораздо больше кода для пользователя, чтобы управлять, и есть мерцание экрана, и трудно отлаживать код. Вот шаги:
-
добавьте этот код в надстройке:
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