[英]Adding controls to a frame in an Excel userform with VBA
I need to create labels and buttons dynamically and then add them to a frame within a userform.我需要动态创建标签和按钮,然后将它们添加到用户窗体中的框架中。 How do I do this?
我该怎么做呢? Seems like it should be easier than it really is.
看起来它应该比实际更容易。
The following code demonstrates how you can dynamically populate a frame in a userform with controls...以下代码演示了如何使用控件动态填充用户窗体中的框架...
In the form I used I had a frame control named Frame1, so in the UserForm_Initialize you call Frame1.Controls.Add to embed a control in the frame.在我使用的窗体中,我有一个名为 Frame1 的框架控件,因此在 UserForm_Initialize 中调用 Frame1.Controls.Add 将控件嵌入到框架中。 You can set the control which gets returned to a WithEvents control variable that you have defined in the UserForm code module so you can respond to events on whatever controls you want...
您可以设置返回到您在 UserForm 代码模块中定义的 WithEvents 控件变量的控件,以便您可以响应您想要的任何控件上的事件...
So with this method you need to pre-write any event code you want for any controls you create...因此,使用此方法,您需要为您创建的任何控件预先编写所需的任何事件代码...
Also note that you can position and size your controls even if the top, left, width, and height properties don't necessarily come up in intellisense...另请注意,即使顶部、左侧、宽度和高度属性不一定出现在智能感知中,您也可以定位和调整控件的大小...
Private WithEvents Cmd As MSForms.CommandButton
Private WithEvents Lbl As MSForms.Label
Private Sub UserForm_Initialize()
Set Lbl = Frame1.Controls.Add("Forms.Label.1", "lbl1")
Lbl.Caption = "Foo"
Set Cmd = Frame1.Controls.Add("Forms.CommandButton.1", "cmd1")
End Sub
Private Sub Cmd_Click()
Cmd.Top = Cmd.Top + 5
End Sub
Private Sub Lbl_Click()
Lbl.Top = Lbl.Top + 5
End Sub
My variation on the theme above.我对上述主题的变体。 This is just for a 4x4 array of buttons though.
不过,这仅适用于 4x4 按钮阵列。 Create a userform and add this to its code.
创建一个用户表单并将其添加到其代码中。 The same concepts can be used with your labels (or see the previous answer):
相同的概念可以与您的标签一起使用(或参见上一个答案):
Private cmdLots(20) As MSForms.CommandButton
Private Sub UserForm_Initialize()
For i = 1 To 4
For j = 1 To 4
k = i + (4 * j)
Set cmdLots(k) = UserForm2.Controls.Add("Forms.CommandButton.1", "cmd1")
With cmdLots(k)
.Top = i * 25
.Left = (j * 80) - 50
.BackColor = RGB(50 * i, 50 * j, 0)
.Caption = "i= " & i & " j= " & j
End With
Next j
Next i
End Sub
Add
Method Add
方法To add controls to a userform or a frame you use the add
method.要将控件添加到用户窗体或框架,请使用
add
方法。
SetControl = object.Add(ProgID [, Name [, Visible ]] )
The first argument is going to reference what type of control you want to add, and it is ProgID
which is defined as第一个参数将引用您要添加的控件类型,它是
ProgID
,定义为
Programmatic identifier.
编程标识符。 A text string with no spaces that identifies an object class.
标识对象类的不含空格的文本字符串。 The standard syntax for a ProgID is ... A ProgID is mapped to a class identifier (CLSID).
ProgID 的标准语法是... ProgID 映射到类标识符 (CLSID)。
To make this process easier, let's use an enum to help manage the various controls for us.为了使这个过程更容易,让我们使用枚举来帮助我们管理各种控件。
' List of all the MSForms Controls.
Public Enum MSFormControls
CheckBox
ComboBox
CommandButton
Frame
Image
Label
ListBox
MultiPage
OptionButton
ScrollBar
SpinButton
TabStrip
TextBox
ToggleButton
End Enum
With this enum, we can now easily create a function to get the ProgID string for all controls.有了这个枚举,我们现在可以轻松创建一个函数来获取所有控件的 ProgID 字符串。
' Gets the ProgID for each individual control. Used to create controls using `Object.add` method.
' @see https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/add-method-microsoft-forms
Public Function GetMSFormsProgID(control As MSFormControls) As String
Select Case control
Case MSFormControls.CheckBox: GetMSFormsProgID = "Forms.CheckBox.1"
Case MSFormControls.ComboBox: GetMSFormsProgID = "Forms.ComboBox.1"
Case MSFormControls.CommandButton: GetMSFormsProgID = "Forms.CommandButton.1"
Case MSFormControls.Frame: GetMSFormsProgID = "Forms.Frame.1"
Case MSFormControls.Image: GetMSFormsProgID = "Forms.Image.1"
Case MSFormControls.Label: GetMSFormsProgID = "Forms.Label.1"
Case MSFormControls.ListBox: GetMSFormsProgID = "Forms.ListBox.1"
Case MSFormControls.MultiPage: GetMSFormsProgID = "Forms.MultiPage.1"
Case MSFormControls.OptionButton: GetMSFormsProgID = "Forms.OptionButton.1"
Case MSFormControls.ScrollBar: GetMSFormsProgID = "Forms.ScrollBar.1"
Case MSFormControls.SpinButton: GetMSFormsProgID = "Forms.SpinButton.1"
Case MSFormControls.TabStrip: GetMSFormsProgID = "Forms.TabStrip.1"
Case MSFormControls.TextBox: GetMSFormsProgID = "Forms.TextBox.1"
Case MSFormControls.ToggleButton: GetMSFormsProgID = "Forms.ToggleButton.1"
End Select
End Function
And lastly, let's create a function that adds to a form or frame using our new function.最后,让我们创建一个使用我们的新函数添加到表单或框架的函数。
' Easly add control to userform or a frame.
' @returns {MSForms.control} The control that was created
Public Function AddControl(userformOrFrame As Object _
, control As MSFormControls _
, Optional name As String = vbNullString _
, Optional visable As Boolean = True _
) As MSForms.control
Set AddControl = userformOrFrame.Controls.Add(GetMSFormsProgID(control), name, visable)
End Function
The beauty of using enums like this is that we now have a intellisense for all the controls and don't have to memorize them all.像这样使用枚举的美妙之处在于我们现在对所有控件都有智能感知,而不必记住所有控件。
To demo it, we can add every control to a blank userform by looping the enum.为了演示它,我们可以通过循环枚举将每个控件添加到一个空白的用户窗体中。
Private Sub UserForm_Initialize()
demoAddingControlsToUserform
End Sub
Private Sub demoAddingControlsToUserform()
' Offset used to prevent controls
' overlapping as well as provide
' a height for the scrollbars
Dim offsetHeight As Double
' Add each control to the userform
' and set top to make sure they are not overlapping
' (Although this looks odd, you can actually loop enums this way.)
Dim control As MSFormControls
For control = CheckBox To ToggleButton
With AddControl(Me, control)
.Top = offsetHeight
offsetHeight = offsetHeight + .Height
End With
Next
' Show scrollbars and adjust the height to show
' all the added controls.
With Me
.ScrollBars = fmScrollBarsVertical
.ScrollHeight = offsetHeight + 20
End With
End Sub
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.