简体   繁体   English

如何从宏运行用户窗体?

[英]How can I run a userform from a macro?

I developed many UDFs and macros in VBA for Excel 2016. One of my macros uses an Inputbox to get data used subsequently by the macro. 我在VBA中为Excel 2016开发了许多UDF和宏。我的一个宏使用Inputbox来获取宏随后使用的数据。 I want to replace the Inputbox with a user form. 我想用用户表单替换Inputbox。 I have created the user form, with one text box. 我创建了带有一个文本框的用户表单。 I want to activate the user form, populating the text box with the default data, and return the text box data to the macro when OK is selected. 我想激活用户窗体,使用默认数据填充文本框,并在选择“确定”时将文本框数据返回到宏。 I have searched extensively for an end-to-end example for all the the code needed to do this, with no luck. 我已经在一个端到端的示例中进行了广泛的搜索,以查找完成此操作所需的所有代码,但是没有运气。 Does an example for this simple problem exist? 是否存在针对此简单问题的示例?

There is an example of how you can pass the value to a form and get the result back. 有一个示例,说明如何将值传递给表单并返回结果。 The approach uses Scripting.Dictionary object created within standard module scope and passed to userform to allow values to be changed. 该方法使用在标准模块范围内创建并传递给用户窗体的Scripting.Dictionary对象,以允许更改值。 So it makes possible to send the default values to userform, and keep the result values in the dictionary even after the userform is closed and unloaded. 因此,可以将默认值发送到用户窗体,并且即使在关闭和卸载用户窗体后也可以将结果值保留在字典中。 You may have multiple values, just add the necessary quantity of keys to the dictionary, eg oData("property1") , oData("property2") , etc. 您可能有多个值,只需将必要数量的键添加到字典中,例如oData("property1")oData("property2")等。

Add a standard module to the project and put the below code into it: 在项目中添加一个标准模块,并将以下代码放入其中:

Option Explicit

Sub Test()

    Dim oData

    ' Set default value and show form
    Set oData = CreateObject("Scripting.Dictionary")
    oData("") = "Some default text"
    UserForm1.ShowForm oData
    ' Wait until user close form
    Do While IsUserFormLoaded("UserForm1")
        DoEvents
    Loop
    ' Output returned value
    MsgBox oData("")

End Sub

Function IsUserFormLoaded(UserFormName As String) As Boolean

    Dim oUF As Object

    For Each oUF In UserForms
        If LCase(oUF.Name) = LCase(UserFormName) Then
            IsUserFormLoaded = True
            Exit Function
        End If
    Next

End Function

Add a userform module named UserForm1 to the project, place controls as shown: 将名为UserForm1模块添加到项目中,放置控件,如下所示:

用户表格

And put the below code into the userform module : 并将以下代码放入userform模块:

Private opData

Public Sub ShowForm(oData)

    Set opData = oData
    Me.TextBox1.Value = opData("")
    Me.Show

End Sub

Private Sub UserForm_Initialize()

    If TypeName(opData) <> "Dictionary" Then Set opData = CreateObject("Scripting.Dictionary")

End Sub

Private Sub CommandButton1_Click()

    Unload Me

End Sub

Private Sub CommandButton2_Click()

    opData("") = Me.TextBox1.Value
    Unload Me

End Sub

Add a Property to your user form. 将属性添加到您的用户表单。 For this answer, let us use the following code within the user form. 对于这个答案,让我们在用户表单中使用以下代码。

Public Property Get MyResult() As String
    ' You may want to do any manipulation here
    ' including converting to a number, in which case the return type should be changed (*)
    MyResult = TextBox1.Text
End Property

(*) If you are doing conversion, you can have another function in your user form to disable the "OK" button until they have valid convertible data in the text box. (*)如果要进行转换,则可以在用户窗体中使用另一个功能来禁用“确定”按钮,直到文本框中包含有效的可转换数据为止。

You also want to know if they have hit "Cancel" 您还想知道他们是否点击了“取消”

Public Property Get Cancelled() As Boolean
    Cancelled = pCancelled ' Declare pCancelled as a Boolean in the scope of the form
End Property

Public Sub CancelButton_Click() ' Standard click event for the button
    pCancelled = True
    Me.Hide
End Sub

Public Sub OKButton_Click() ' Standard click event for the button
    pCancelled = False
    Me.Hide
End Sub

In your calling macro 在您的呼叫巨集中

MyForm.Show ' This is modal, so will block execution until a response is provided
If Not MyForm.Cancelled Then
    Debug.Print MyForm.MyResult
    'Do something with MyForm.MyResult
End If
UnLoad MyForm ' assuming you do not want to re-use this form as part of your logic.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM