如何在Access窗体中有效地配对切换按钮和文本框?

时间:2018-02-10 15:03:52

标签: vba forms ms-access togglebutton

我知道标题有点令人困惑,所以让我尽可能清楚自己 在Access表单(2010)中,我有一组文本字段用于包含日期。这些字段都是可选的,用户可以填写任意数量的日期。 为了使其更加用户友好,我想将每个字段与切换按钮相关联。然后我想要发生两件事:

关于CURRENT事件:

  • 如果文字字段的值为,则可见和切换按钮 与此相关联的是按下
  • 如果文字字段为空,则不可见,并且未按下切换按钮

点击切换按钮时

  • 如果与其关联的文本字段具有值,则此字段将被清除(并且不可见),并且切换按钮将被取消按下;
  • 如果与之关联的文本字段为空,则会在其上设置焦点并按下切换按钮(如果在文本字段中输入值,则保持这种状态,否则一切都会恢复原样,看不见的和未看过的。)

到目前为止,我已经通过基于我在网上找到的一些示例设置两个控件集来实现了第一步。 因此,当表单加载时,我称之为:

  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中重复一些线。
在程序中区分文本框和按钮似乎很奇怪,我觉得应该事先做好,这样我就不必在每个程序中都这样做了。我也觉得循环每对控件(文本+按钮)而不是两个集合中的每个控件都会更好。

基本上,我想知道是否(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
...

我的猜测是,我需要创建一个公共子,我根据他们的标签设置一组按钮和文本字段(我的表单中还有其他控件需要单独留下)和名称,但是我不知道怎么样,我是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

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

现在我更关注点击和丢失焦点事件的数量。我宁愿让一些公共函数和事件处理程序处理它,但它对我来说太复杂了。当我了解更多......一切时,我会回到它。

无论如何仍然欢迎建议=)!

1 个答案:

答案 0 :(得分:1)

由于您的控制对无论如何都是按名称“配对”,因此您不需要任何花哨的构造,甚至不需要第二个集合。只需通过名称直接解决匹配控件。

不是使用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