如何有效地将 Access 表单中的切换按钮和文本框配对?

How do I efficiently pair Toggle Buttons and Textboxes in Access Form?

我知道标题有点混乱,所以让我尽可能说清楚。
在 Access 表单 (2010) 中,我有一组包含日期的文本字段。这些字段都是可选的,用户可以填写任意数量的日期。 为了让它更 user-friendly,我想将每个字段关联到一个切换按钮。然后我希望发生两件事:

当前事件:

单击切换按钮时:

到目前为止,我已经完成了第一步,根据我在网上找到的一些示例设置了两个 collection 控件。 所以,当加载表单时,我称之为:

  Private mcolGroupTxToggle As New Collection
  Private mcolGroupBuToggle As New Collection

  Private Sub InitializeCollections()
    Dim ctl As Control

    If mcolGroupTxToggle.Count = 0 Then
       For Each ctl In Me.Controls
         If ctl.Tag = "txtoggle" Then
            mcolGroupTxToggle.Add ctl, ctl.Name
         End If
       Next ctl
       Set ctl = Nothing
    End If

    If mcolGroupBuToggle.Count = 0 Then
       For Each ctl In Me.Controls
         If ctl.Tag = "butoggle" Then
            mcolGroupBuToggle.Add ctl, ctl.Name
         End If
       Next ctl
       Set ctl = Nothing
    End If

  End Sub

在 Form_Current 事件中,我称之为:

  Private Sub OnLoadToggles(mcol As Collection, pcol As Collection)
    Dim ctl As Control
    Dim btn As Control
    Dim strBtn As String

    For Each ctl In mcol
    'Every button has the same name than the textbox + "b"
    strBtn = ctl.Name & "b"

        For Each btn In pcol
        If btn.Name = strBtn Then
            If IsNull(ctl) Then
                ctl.Visible = False
                btn.Value = False
            Else
                ctl.Visible = True
                btn.Value = True
            End If
        End If
        Next btn

    Next ctl
    Set ctl = Nothing

  End Sub

到目前为止一切正常,但我不确定这是最好的方法,我想我需要在步骤 2 中重复一些行。
在程序中区分文本框和按钮似乎很奇怪,我觉得应该事先完成,这样我就不必在每个程序中都这样做。我还觉得循环遍历每对控件(文本 + 按钮)而不是 collections 中的每个控件会更好。

基本上,我想知道是否 (1) 更好和 (2) 可能有像这样简单的东西:

Private Sub OnLoadToggles(Collection of pairs)
for each [pair of txt and btn]
  if isnull(txt) Then
    txt.visible = false
    btn.value = false
  else
  ...
  end if
...

我的猜测是我需要创建一个 public 子节点,在其中我根据它们的标签设置 collection 对按钮和文本字段(我的表单中还有其他控件需要一个人呆着)和名字,但我不确定如何,我是 VBA.

的初学者

有什么建议吗?

-- 编辑步骤 2 --

感谢 Andre 的回答,第二部分比我想象的要容易。我已经更新了我的 sample database。所以在点击事件上我称之为:

Private Sub ClickToggles()
    Dim ctl As Control
    Dim btn As Control
    Dim strBtn As String
    Dim strCtl As String

    strBtn = Me.ActiveControl.Name
    strCtl = Left(strBtn, Len(strBtn) - 1)
    Set ctl = Me(strCtl)
    Set btn = Me(strBtn)

        If IsNull(ctl) Then
            btn.Value = True
            ctl.Visible = True
            ctl.Enabled = True
            ctl.SetFocus
        Else
            ctl.Value = ""
            btn.Value = False
            ctl.Visible = False
        End If

End Sub

它并不完美,但它确实有效。此时清除数据可能不是一个好主意,因为可能会发生误点击。最好在保存表单之前循环遍历文本框,并从 collection 中清除不可见的 and/or 禁用控件的值。我可能稍后再说。
我必须在 .visible 旁边添加 .enabled 属性,因为在 lostfocus 事件中我收到一条错误消息,提示控件仍处于活动状态,因此无法使其不可见。

现在我更关心点击和失去焦点事件的数量。我宁愿有一些 public 函数和事件处理程序来处理它,但它对我来说太复杂了。当我对……一切了解得更多时,我会回来的。

仍然欢迎大家提出建议 =) !

由于您的控制对的名称无论如何都是 "paired",因此您不需要任何花哨的构造,甚至不需要第二个集合。只需直接通过名称对匹配的控件进行寻址即可。

与使用 If/Else 设置布尔属性相比,通常更容易将变量分配给 属性。

Private Sub OnLoadToggles(mcol As Collection)

    Dim ctl As Control
    Dim btn As Control
    Dim strBtn As String
    Dim bShowIt As Boolean

    For Each ctl In mcol
        'Every button has the same name than the textbox + "b"
        strBtn = ctl.Name & "b"
        ' If you have the control name, you can get the control directly:
        Set btn = Me(strBtn)

        ' Using a variable you don't need If/Else
        bShowIt = Not IsNull(ctl.Value)

        ctl.Visible = bShowIt
        btn.Value = bShowIt

    Next ctl

    ' Note: this is not necessary for local variables - they go automatically out of scope
    Set ctl = Nothing

End Sub