Передача переменной из формы в модуль в VBA

У меня есть следующая кнопка в форме:

Private Sub CommandButton1_Click()
 Dim pass As String
 pass = UserForm1.TextBox1
 Unload UserForm1
End Sub

Затем у меня есть модуль под названием Module1:

 Public Sub Login()

 ...

 UserForm1.Show
 driver.findElementByName("PASSWORD").SendKeys pass

 ...

End Sub

Идея состоит в том, что любой пароль, который пользователи вводят в поле ввода, будет назначен переменной pass. Однако у меня возникают проблемы с передачей pass из UserForm1 в подпрограмму Login Module1.

Я бы подумал, что добавить что-то вроде Module1.Login (pass) в мою форму, прежде чем я выгружу ее, сработает, однако это, похоже, ничего не передает. Любая помощь приветствуется. Спасибо.


person JimmyK    schedule 26.11.2013    source источник


Ответы (2)


Не объявляйте переменную в пользовательской форме. Объявите его как Public в модуле.

Public pass As String

В форме пользователя

Private Sub CommandButton1_Click()
    pass = UserForm1.TextBox1
    Unload UserForm1
End Sub

В модуле

Public pass As String

Public Sub Login()
    '
    '~~> Rest of the code
    '
    UserForm1.Show
    driver.findElementByName("PASSWORD").SendKeys pass
    '
    '~~> Rest of the code
    '
End Sub

Возможно, вы захотите добавить дополнительную проверку непосредственно перед вызовом линии driver.find...?

If Len(Trim(pass)) <> 0 Then

Это гарантирует, что пустая строка не будет передана.

person Siddharth Rout    schedule 26.11.2013
comment
+1 Сид, это хороший способ сделать это. В качестве альтернативы вы можете скрыть Userform1 вместо его выгрузки и получить доступ к UserForm1.TextBox1 из модуля, а затем выгрузить userform1, но решение о подходе зависит от всей реализации - person ; 26.11.2013
comment
Ахах, я никогда не думал объявлять переменную как Public. Это отличный совет, и мне придется начать делать больше, спасибо! - person JimmyK; 26.11.2013
comment
@ user2140173 Лучше всего выгрузить форму, как только вы с ней закончите. Лучше для памяти и безопасности. - person TylerH; 19.04.2017
comment
@TylerH только потому, что вы работаете с экземпляром формы по умолчанию. Относитесь к формам как к объектам, которыми они являются, а не как к пользовательскому интерфейсу глобального состояния, и аргументы как памяти, так и безопасности больше не действуют. - person Mathieu Guindon; 04.07.2017

Ответ Сиддхарта хорош, но он полагается на глобальные переменные. Есть лучший способ, более дружественный к ООП.

UserForm - это модуль класса, как и любой другой, с той лишь разницей, что у него есть скрытый атрибут VB_PredeclaredId, установленный на True, что заставляет VB создавать объектную переменную с глобальной областью видимости, названную в честь класса - вот как вы можете писать UserForm1.Show без создания нового экземпляр класса.

Отойдите от этого и вместо этого рассматривайте свою форму как объект - выставляйте Property Get члены и абстрагируйте элементы управления формы - вызывающий код в любом случае не заботится о элементах управления:

Option Explicit
Private cancelling As Boolean

Public Property Get UserId() As String
    UserId = txtUserId.Text
End Property

Public Property Get Password() As String
    Password = txtPassword.Text
End Property

Public Property Get IsCancelled() As Boolean
    IsCancelled = cancelling
End Property

Private Sub OkButton_Click()
    Me.Hide
End Sub

Private Sub CancelButton_Click()
    cancelling = True
    Me.Hide
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If CloseMode = VbQueryClose.vbFormControlMenu Then
        cancelling = True
        Cancel = True
        Me.Hide
    End If
End Sub

Теперь вызывающий код может это сделать (при условии, что пользовательская форма была названа LoginPrompt):

With New LoginPrompt
    .Show vbModal
    If .IsCancelled Then Exit Sub
    DoSomething .UserId, .Password
End With

Где DoSomething - это некоторая процедура, требующая двух строковых параметров:

Private Sub DoSomething(ByVal uid As String, ByVal pwd As String)
    'work with the parameter values, regardless of where they came from
End Sub
person Mathieu Guindon    schedule 14.07.2016
comment
Обратная связь @RandomDownvoter всегда приветствуется; Я всегда открыт для новых способов улучшить свои ответы. Прямо сейчас я озадачен тем, что не так в том, чтобы избежать глобального состояния и повысить выразительность и надежность кода с помощью простой абстракции. Ваше здоровье. - person Mathieu Guindon; 21.08.2018
comment
Мне нравится такой подход к отделению формы от данных и методов. Как бы я реализовал это так, чтобы пользовательская форма оставалась видимой. Используя приведенный выше пример, предположим, что идентификатор или пароль вернулись неверно, может ли форма оставаться открытой и выдавать какое-то предупреждение? - person Robert Todar; 06.12.2018
comment
@RobertTodar, в этом случае вы должны объявить событие в представлении / форме и обработать его в презентаторе (который тогда должен быть модулем класса с объявлением WithEvents для представления / формы). Немного похоже на логику «Применить» для диалогового окна UserForm < / а> - person Mathieu Guindon; 06.12.2018
comment
Большое спасибо за информацию, я читаю сайт и сейчас практикуюсь с моим собственным кодом. К вашему сведению, ссылка для скачивания больше не работает на этом сайте. Еще раз спасибо! - person Robert Todar; 06.12.2018
comment
@RobertTodar работает для меня - вроде - я не ожидал, что Dropbox будет просто странно просматривать файл прямо в браузере ... когда вы находитесь в Dropbox, в правом верхнем углу есть кнопка загрузки. Не забудьте проверить Rubberduck, пока вы там! (и отметьте нас на GitHub!) - person Mathieu Guindon; 06.12.2018
comment
@Hend спасибо за предупреждение! обратите внимание, что этот код вызывает Me.Hide, и у меня никогда не было проблем с этим (хотя это немного упрощено, я фактически поместил переключатель состояния + форма скрытия в частный метод OnCancel, который я вызываю как из QueryClose, так и из какой-то CancelButton_Click обработчик; в коде в связанном вопросе отсутствует скрытие формы, а отсутствие Cancel = True - это то, что вызывает ошибку, потому что не отмена этого приводит к самоуничтожению объекта формы. Я исправляю это, спасибо! - person Mathieu Guindon; 26.09.2020