#excel #vba
#превосходить #vba
Вопрос:
У меня есть эта форма пользователя, в которой я использую a property get
. Это работает таким образом:
1.Если нажать кнопку «Ок», форма пользователя скрывается и запускается процедура в модуле.
2.Если ничего не выбрано, появится окно MsgBox, и форма пользователя будет отображаться снова, пока не будет выбрана опция
3.Если нажата кнопка «отмена», информация должна быть выгружена и выйти из макроса.
Проблема в том, что третьего шага не происходит. При нажатии кнопки «отмена» property get
запускается. Кроме того, если пользователь не выбирает какой-либо параметр дважды, процедура в модуле все равно запускается, что приводит к ошибке. Я предполагаю, что проблема связана с тем, чтобы не вызывать property get
внутреннюю процедуру «ОК». Есть какие-нибудь предложения, как мне это сделать?
В форме пользователя
Private Sub cmdAceptar_Click() Me.Hide End Sub Private Sub cmdCerrar_Click() Unload Me End Sub Public Property Get Sup() As String If optSupA = True Then Sup = "SuplierA" ElseIf optSupB = True Then Sup = "SuplierB" ElseIf optSupC = True Then Sup = "SuplierC" Else MsgBox "A suplier should be selected", vbExclamation Me.Show End If End Property
В модуле
Dim result as String Public Sub TEST() 'Show userform modal frmSuplier.Show vbModal result = frmSuplier.Sup 'Call Calculate_prices Call Calculate_price(result) 'now unload the form Unload frmSuplier End Sub
Ответ №1:
Мое предложение состоит в том, чтобы переместить все дерево IF/ELSE, чтобы оно находилось внутри Control_Change
событий для любых частей формы пользователя, которые захватывают значение optSupA
, optSupB
, optSupC
. Это Property Get Sup
должно выглядеть так, как будто Sup = SavedValue
нет MsgBox или взаимодействия с элементами управления формой пользователя.
Предполагая, что есть 3 кнопки выбора, вот как бы я это настроил:
Private SupValue As String Private Sub cmdAceptar_Click() If Me.OptionButton1.Value Or Me.OptionButton2.Value Or Me.OptionButton3.Value Then Me.Hide Else 'None of the options are currently selected MsgBox "A suplier should be selected", vbExclamation End If End Sub Private Sub cmdCerrar_Click() Unload Me End Sub Public Property Get Sup() As String Sup = SupValue End Property Private Sub OptionButton1_Change() If Me.OptionButton1.Value Then Me.OptionButton2.Value = False Me.OptionButton3.Value = False SupValue = "SupplierA" End If End Sub Private Sub OptionButton2_Change() If Me.OptionButton2.Value Then Me.OptionButton1.Value = False Me.OptionButton3.Value = False SupValue = "SupplierB" End If End Sub Private Sub OptionButton3_Change() If Me.OptionButton3.Value Then Me.OptionButton1.Value = False Me.OptionButton2.Value = False SupValue = "SupplierC" End If End Sub
С этими изменениями кнопка отмена Выгружает форму пользователя, удаляя значение SupValue. Таким образом, в вашем модуле result
будет пусто, и вы можете добавить if/else для обработки таких ситуаций, как If result = "" Then Exit Sub
Выгрузка с помощью кнопки «Отмена», а затем вызов frmSuplier.Sup
фактически повторно инициализирует форму. Поэтому, чтобы избежать этой двойной инициализации и двойной выгрузки, измените кнопку отмена на:
Private Sub cmdCerrar_Click() SupValue = "" Me.Hide End Sub
Таким образом, вы все еще получаете result = ""
, когда пользователь нажимает «Отмена», но вы выполняете только одну загрузку и выгрузку.
Комментарии:
1. Спасибо @Toddleson за ваше предложение, это было именно то, что я хотел сделать. Я немного новичок в использовании формы пользователя, но когда вы используете
Me.
объект для ссылки на объект формы пользователя, не так ли?2. @vbabeginner
Me
ссылается на владельца модуля кода. Поэтому, если бы вы поместили этот код в модуль кода рабочего листа, онMe
бы ссылался на объект рабочего листа. Поскольку мы помещаем его в модуль кода формы пользователя, онMe
ссылается на объект формы пользователя. Мне нравится использоватьMe
, потому что это делает код универсальным и его можно легко копировать и вставлять между проектами.