【问题标题】:Re-write dynamic textbox after button is pressed按下按钮后重写动态文本框
【发布时间】:2017-11-12 18:23:41
【问题描述】:

我在 VBA 中创建了一个代码来使用多页控件收集数据。在每个页面中,我根据 Excel 工作表中的行动态添加了复选框,并且对于每个复选框,都有一个文本框和 2 个命令按钮,如下图所示:

输入窗口:

自动添加控件的代码是:

Private Sub UserForm_Initialize()
fmat_disp.Value = 0
fmat_set.Value = 0


'---------------------------------------------------------------------------------------------
'Inspeção de Mecânica
Sheets("Mecânica").Activate
n_anom = Application.WorksheetFunction.CountA(Range("1:1")) - 1
AreasInspecao.mecanica.ScrollHeight = 10 + 18 * (n_anom)
For i = 1 To n_anom
'Selecionar anomalia
Set SelAnom = AreasInspecao.mecanica.Controls.Add("Forms.CheckBox.1", "sel_anom_" & i)
SelAnom.Caption = Worksheets("Mecânica").Cells(1, i + 1)
SelAnom.AutoSize = True
SelAnom.Height = 18
SelAnom.Left = 5
SelAnom.Top = 5 + (SelAnom.Height) * (i - 1)
SelAnom.Tag = i

文本框和加号/减号按钮也是如此,只是更改了标题。

我想要的是: 1) 当CHECKBOX被CHECKED时,相应的TEXTBOX必须显示1 2)当减号被按下时,相应的文本框必须递减 3)当加号被按下时,相应的文本框必须增加 4) 当“Finalizar Inspeção”被按下时,所有收集的数据必须发送到 Excel,填写工作表。

我根本不知道如何在不为每个按钮/复选框创建子例程的情况下将每个按钮/复选框链接到您各自的文本框!我将有大约 500 个子例程......这是无法手动管理的......

【问题讨论】:

  • 图片在哪里?
  • 抱歉...已添加图片的imgurl链接!
  • 如果您要动态添加控件,那么您需要这样的东西:siddharthrout.com/2011/08/05/vba-control-arrays 这向您展示了如何捕获事件:您需要做的就是为您的控件命名,以便相关控件组可以在触发代码中识别出来。
  • 但在我的情况下,对于每个文本框,只有它们旁边的两个按钮(加号/减号)控制它...这将需要我为每个文本框创建事件?还是我错了?
  • 您需要遵循链接中显示的方法的两个类实例集合:一个用于复选框,一个用于按钮。文本框不会在您描述的过程中引发任何事件。

标签: excel checkbox dynamic vba


【解决方案1】:

好的,这里是处理复选框和按钮上的点击事件的粗略大纲。

前两个用于捕获点击的自定义类:每一个都非常简单——它们所做的只是调用用户窗体上的一个方法,并将点击的控件作为参数。

'clsCheck
Public WithEvents chk As MSForms.CheckBox

Private Sub chk_Click()
    frmExample.HandleClick chk
End Sub

'clsButton
Public WithEvents btn As MSForms.CommandButton

Private Sub btn_Click()
    frmExample.HandleClick btn
End Sub

用户表单代码 - 我的表单名为“frmExample”。

请注意允许将控件组视为“单元”的命名约定。

Option Explicit

'These two global collections hold instances of the custom classes
Dim colCheckBoxes As Collection
Dim colButtons As Collection


Private Sub UserForm_Activate()

    Const CON_HT As Long = 18
    Dim x As Long, cbx As MSForms.CheckBox, t
    Dim btn As MSForms.CommandButton, txt As MSForms.TextBox
    Dim oCheck As clsCheck, oButton As clsButton

    Set colCheckBoxes = New Collection
    Set colButtons = New Collection

    For x = 1 To 10

        t = 5 + CON_HT * (x - 1)

        Set cbx = Me.Controls.Add("Forms.CheckBox.1", "cbox_" & x)
        cbx.Caption = "Checkbox" & x
        cbx.Width = 80
        cbx.Height = CON_HT
        cbx.Left = 5
        cbx.Top = t
        colCheckBoxes.Add GetCheckHandler(cbx) '<< save in collection

        Set btn = Me.Controls.Add("Forms.CommandButton.1", "btnplus_" & x)
        btn.Caption = "+"
        btn.Height = CON_HT
        btn.Width = 20
        btn.Left = 90
        btn.Top = t
        btn.Enabled = False '<<buttons start off disabled
        colButtons.Add GetButtonHandler(btn) '<< save in collection

        Set btn = Me.Controls.Add("Forms.CommandButton.1", "btnminus_" & x)
        btn.Caption = "-"
        btn.Height = CON_HT
        btn.Width = 20
        btn.Left = 130
        btn.Top = t
        btn.Enabled = False '<<buttons start off disabled
        colButtons.Add GetButtonHandler(btn) '<< save in collection

        'no events are captured for the textboxes...
        Set txt = Me.Controls.Add("Forms.Textbox.1", "txt_" & x)
        txt.Width = 30
        txt.Height = CON_HT
        txt.Left = 170
        txt.Top = t

    Next x

End Sub

'All "clicked" controls saved in instances of the custom classes
'   get passed here. Handle based on control type/name
Public Sub HandleClick(ctrl As MSForms.Control)
    Dim num
    num = Split(ctrl.Name, "_")(1) 'which set of controls are we working with?
    Dim txt As MSForms.TextBox
    'get the matching text box...
    Set txt = Me.Controls("txt_" & num)
    If ctrl.Name Like "cbox_*" Then
        If ctrl.Value Then txt.Value = 1
        Me.Controls("btnplus_" & num).Enabled = ctrl.Value
        Me.Controls("btnminus_" & num).Enabled = ctrl.Value
    ElseIf ctrl.Name Like "btnplus_*" Then
        txt.Value = txt.Value + 1
    ElseIf ctrl.Name Like "btnminus_*" Then
        txt.Value = txt.Value - 1
    End If
End Sub


'couple of "factory" functions for the event-handling classes
Private Function GetCheckHandler(cb As MSForms.CheckBox)
    Dim rv As New clsCheck
    Set rv.chk = cb
    Set GetCheckHandler = rv
End Function

Private Function GetButtonHandler(btn As MSForms.CommandButton)
    Dim rv As New clsButton
    Set rv.btn = btn
    Set GetButtonHandler = rv
End Function

示例文件:https://www.dropbox.com/s/k74c08m0zkwn9l7/tmpFormEvents.xlsm?dl=0

【讨论】:

  • 谢谢,蒂姆!它就像一个魅力,虽然我不得不在我的界面中进行一些修改......我想我不能在多页中做到这一点,所以我创建了链接到按钮的框架并一次显示一个框架,基于哪个按钮被激活
猜你喜欢
  • 2021-08-10
  • 1970-01-01
  • 1970-01-01
  • 2011-12-02
  • 2020-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-23
相关资源
最近更新 更多