【问题标题】:Programmatically add and delete Combobox, Textbox and Checkbox to Userform - VBA以编程方式向用户窗体添加和删除组合框、文本框和复选框 - VBA
【发布时间】:2020-08-12 08:57:08
【问题描述】:

我正在创建一个用户表单,它有 1 个组合框 (1)、2 个文本框(2 和 3)和 11 个复选框(AK),如图所示。所有控件的第一个实例都将出现,但是当用户单击 Add Class 时,必须创建一组新的所有控件,并且 Remove Class 应该删除特定行。

我已经设法获得了一个实例的需求,但是我无法弄清楚我该如何做 N 次,并且用户窗体的大小也在扩大。

Private Sub cmdAddClass()

 Dim cCheckBox As Control, r As Long, r1 As Range

 Set r1 = Sheets("Sheet1").Range("A2:A12") 

 Set cComboBox = Me.Controls.Add("Forms.ComboBox.1")
 With cComboBox
  .Height=25.5
  .Width=102
  .Top=50
  .Left =6
 End With

 Set cTextBox = Me.Controls.Add("Forms.TextBox.1")
 With cTextBox
  .Height=25.5
  .Width=54
  .Top=50
  .Left =114
 End With

 For r = 1 To WorksheetFunction.CountA(r1)
  If r1(r) <> vbNullString Then 
   Set cCheckBox = Me.Controls.Add("Forms.CheckBox.1", "Checkbox" & r, True)
    With cCheckBox
     .Width = 21
     .Height = 11
     .Top = 50
     If r = 1 Then
       .Left = 270
     ElseIf r = 2 Then
       .Left = 348
     ElseIf r = 3 Then
       .Left = 420
     ElseIf r = 4 Then
       .Left = 492
     ElseIf r = 5 Then
       .Left = 564
     ElseIf r = 6 Then
       .Left = 636
     ElseIf r = 7 Then
       .Left = 701.95
     ElseIf r = 8 Then
       .Left = 780
     ElseIf r = 9 Then
       .Left = 876
     ElseIf r = 10 Then
       .Left = 966
     Else
       .Left = 1050
     End If
    End With
  End If
 Next r
End Sub

【问题讨论】:

  • 这里有几个提示可以帮助您入门。首先,计算每次按下按钮时 .Top 的值。其次,您不应该在添加控件时扩大表单的大小。相反,您想要实现滚动。第三,您需要在添加和删除控件时重新定位按钮。
  • 您希望添加多少N 次新行?
  • @AlexP 也许在 10-15 左右
  • @BrianMStafford 你能指导我如何计算 .Top 吗?
  • @Cody 不是硬编码的 Top of 50,而是有一个模块级或静态变量来跟踪 Top。每次按下按钮时,都会在顶部添加一个数字,以保持控件的正确间隔。你应该添加什么数字?我不知道,继续调整它直到你喜欢表格的样子。

标签: vba controls userform


【解决方案1】:

这是一个你可以适应的例子。

Private Sub btnAddClass_Click()
    Dim ctrl As Control, newCtrl As Control, offsetTop As Integer

    offsetTop = 30

    For Each ctrl In Me.Controls

        If TypeName(ctrl) <> "CommandButton" Then
            If ctrl.Top = btnAddClass.Top - offsetTop Then
                If TypeName(ctrl) = "ComboBox" Then
                    Set newCtrl = Me.Controls.Add("Forms.ComboBox.1")
                ElseIf TypeName(ctrl) = "TextBox" Then
                    Set newCtrl = Me.Controls.Add("Forms.TextBox.1")
                ElseIf TypeName(ctrl) = "CheckBox" Then
                    Set newCtrl = Me.Controls.Add("Forms.Checkbox.1")
                End If

                With newCtrl
                    .Height = ctrl.Height
                    .Width = ctrl.Width
                    .Top = ctrl.Top + offsetTop
                    .Left = ctrl.Left
                End With

            End If
        End If
    Next ctrl

    btnAddClass.Top = btnAddClass.Top + offsetTop
    btnRemoveClass.Top = btnRemoveClass.Top + offsetTop
    Me.Height = Me.Height + offsetTop
End Sub

Private Sub btnRemoveClass_Click()
    Dim ctrl As Control, offsetTop As Integer

    offsetTop = 30

    For Each ctrl In Me.Controls

        If TypeName(ctrl) <> "CommandButton" Then
            If ctrl.Top = btnAddClass.Top - offsetTop Then
                Me.Controls.Remove (ctrl.Name)
            End If
        End If

    Next ctrl

    btnAddClass.Top = btnAddClass.Top - offsetTop
    btnRemoveClass.Top = btnRemoveClass.Top - offsetTop
End Sub

注意事项:

为了让它工作,我需要解释一下设置:

  1. 您的初始控件行将Top 属性设置为12
  2. 有两个按钮名为btnAddClassbtnRemoveClassTop 设置为42

控件和按钮之间的高度为offset30

要添加新控件,您只需遍历每个控件,创建一个新控件,并将其 Top 设置为现有控件 Top 值 + 偏移量(即 30)。同时将按钮向下移动 30 并将用户窗体高度增加 30。

要删除控件,您可以通过检查相对于btnAddClassTop 属性来获取最后一行。然后删除这些控件并将按钮向上移动 30 并将用户窗体高度减少 30。

【讨论】:

  • 谢谢@alexp 这很好用。但是,当我将第一行从Top12 移动到42 并且78 处的按钮第一个文本框不合适时,我确实遇到了问题。你能指导我吗?仅供参考,我用过Me.ScroolHeight=Application.Height Me.ScroolWidth=Application.Width。当我进入代码时,我可以看到两个文本框都正确放置,但是 for 循环继续运行。
  • 你是否将偏移量调整为 36(即 78 - 42)?
  • 是的,我确实改变了偏移量。
  • Private Sub btnAddClass_Click 中存在错误。我已经在上面更新了。这能解决问题吗?
  • 这超级完美!!非常感谢
猜你喜欢
  • 1970-01-01
  • 2020-11-13
  • 1970-01-01
  • 2017-10-25
  • 2015-05-25
  • 2020-11-15
  • 1970-01-01
  • 1970-01-01
  • 2017-12-23
相关资源
最近更新 更多