Siddharth's answer is nice, but relies on globally-scoped variables. There's a better, more OOP-friendly way.
A UserForm is a class module like any other - the only difference is that it has a hidden VB_PredeclaredId
attribute set to True
, which makes VB create a global-scope object variable named after the class - that's how you can write UserForm1.Show
without creating a new instance of the class.
Step away from this, and treat your form as an object instead - expose Property Get
members and abstract away the form's controls - the calling code doesn't care about controls anyway:
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
Now the calling code can do this (assuming the UserForm was named LoginPrompt
):
With New LoginPrompt
.Show vbModal
If .IsCancelled Then Exit Sub
DoSomething .UserId, .Password
End With
Where DoSomething
would be some procedure that requires the two string parameters:
Private Sub DoSomething(ByVal uid As String, ByVal pwd As String)
'work with the parameter values, regardless of where they came from
End Sub