【问题标题】:Access VBA: use Boolean variable to lock/unlock form controls访问 VBA:使用布尔变量来锁定/解锁表单控件
【发布时间】:2016-08-12 00:27:28
【问题描述】:

我设置了以下公共功能来帮助我锁定和启用(false)或反之亦然,表单上的特定控件。这样我可以锁定/启用它们,或者我可以解锁并启用 A 组或 B 组,具体取决于所选的组合框。我设置了这个,似乎锁定工作正常,但未启用。

我正在传递要翻转的控件组,然后是一个布尔值来将它们锁定为真或假。这些控件的启用属性应该是布尔变量的逆或非变量。

有人可以看看我可能需要调整什么吗?

Public Function CostModelLock(LockType As String, LockOn As Boolean)
    Select Case LockType
        Case "A"
            'Lock A controls
            Forms!frmRequest.AField1.Locked = LockOn
            Forms!frmRequest.AField2.Locked = LockOn
            Forms!frmRequest.AField3.Locked = LockOn

            'Enable A controls
            Forms!frmRequest.AField1.Enabled = Not LockOn
            Forms!frmRequest.AField2.Enabled = Not LockOn
            Forms!frmRequest.AField3.Enabled = Not LockOn

        Case "B"

            'Lock B controls
            Forms!frmRequest.BField1.Locked = LockOn
            Forms!frmRequest.BField2.Locked = LockOn
            Forms!frmRequest.BField3.Locked = LockOn

            'Enable B controls
            Forms!frmRequest.BField1.Enabled = Not LockOn
            Forms!frmRequest.BField2.Enabled = Not LockOn
            Forms!frmRequest.BField3.Enabled = Not LockOn

    End Select
    Forms!frmRequest.Repaint
End Function

编辑 - 继续:

是的,我正在尝试将其锁定并禁用使其变灰。我可以翻转可见性,但我试图避免这种情况,因此用户可以填写两者,如果它适用,但一次只有一组活动。我希望那些不是他们选择的选项的选项显示为灰色,因此很明显这些字段没有发挥作用。我有一个组合框,这是用户选择他们需要的集合的方式,并且此功能在该组合更新后运行。

在加载表单时,我在两个集合上都运行了这个函数,以确保它们被锁定。那是因为表单加载时没有记录。他们必须使用组合来查找请求,或者单击“新建”来开始新的请求。在更新后,我有以下代码:

If Nz(Me.FKCostModelType.Value) <> 0 Then
    If Me.FKCostModelType.Column(0) = 1 Then
        Call CostModelLock("A", False)
        Call CostModelLock("B", True)
    ElseIf Me.FKCostModelType.Column(0) = 2 Then
        Call CostModelLock("B", False)
        Call CostModelLock("A", True)
    End If
ElseIf Nz(Me.FKCostModelType.Value) = 0 Then
    Call CostModelLock("A", True)
    Call CostModelLock("B", True)
End If

我尝试将功能顺序切换为禁用然后锁定,但这也不起作用。我还将上面的代码添加到查找请求中,以便在找到请求后,正确设置该部分。我已经更新了上面最初发布的代码,添加了一个由 if 语句设置的变量,以设置传递给函数的布尔值的逆,因此我可以更轻松地将相反的布尔值传递给控件。

Public Function CostModelLock(LockType As String, LockOn As Boolean)
    Dim NotLockOn As Boolean

    If LockOn = True Then
        NotLockOn = False
    Else
        NotLockOn = True
    End If

    Select Case LockType
        Case "A"
            'Enable A controls
            Forms!frmRequest.AField1.Enabled = NotLockOn
            Forms!frmRequest.AField2.Enabled = NotLockOn
            Forms!frmRequest.AField3.Enabled = NotLockOn

            'Lock A controls
            Forms!frmRequest.AField1.Locked = LockOn
            Forms!frmRequest.AField2.Locked = LockOn
            Forms!frmRequest.AField3.Locked = LockOn

        Case "B"
            'Enable B controls
            Forms!frmRequest.BField1.Enabled = NotLockOn
            Forms!frmRequest.BField2.Enabled = NotLockOn
            Forms!frmRequest.BField3.Enabled = NotLockOn

            'Lock B controls
            Forms!frmRequest.BField1.Locked = LockOn
            Forms!frmRequest.BField2.Locked = LockOn
            Forms!frmRequest.BField3.Locked = LockOn

    End Select
    Forms!frmRequest.Repaint
End Function

这没什么大不了的。我可能只是删除启用的属性设置,看看我是否可以像启用的属性一样将它们变灰。

感谢大家的回复!从真正擅长这方面的开发人员那里获得建议会很有帮助。


继续:

好的,所以我再次重写了它,但它仍然无法按我的意愿工作,我不确定我做错了什么。下面是公共功能,然后是组合的更新后,用户在其中选择他们想要的模型,该功能会触发以适当地设置 2 组控件。

公共职能代码:

Public Function CostModelLock(TagType As String, LockOn As Boolean)
    Dim frm As Form
    Dim ctl As Control
    Dim bColor As String

    Set frm = Forms!frmRequest
    If LockOn = True Then
        bColor = RGB(192, 192, 192)
    Else
        bColor = vbWhite
    End If

    'Loop through every control on the form
    For Each ctl In frm.Controls
    'Look for a Particular Tag
        If ctl.Tag = TagType And (TypeOf ctl Is TextBox Or TypeOf ctl Is ComboBox) Then
            ctl.Locked = LockOn
            ctl.BackColor = bColor
        End If
    Next ctl
    frm.Repaint
End Function

更新连击后触发公共功能:

Private Sub FKCostModelType_AfterUpdate()
    If Nz(Me.FKCostModelType.Value) <> 0 Then
        If Me.FKCostModelType.Column(0) = 1 Then
            Call CostModelLock("ReqA", False)
            Call CostModelLock("ReqB", True)
        ElseIf Me.FKCostModelType.Column(0) = 2 Then
            Call CostModelLock("ReqB", False)
            Call CostModelLock("ReqA", True)
        End If
    ElseIf Nz(Me.FKCostModelType.Value) = 0 Then
        Call CostModelLock("ReqA", True)
        Call CostModelLock("ReqB", True)
    End If
    Call UpdateCostEstimate
End Sub

我还有一个组合代码来查找记录。就是这样:

Private Sub cboFindRequest_AfterUpdate()
    Dim ctl As Control
    Me.RecordSource = "SELECT * FROM tblRequest"
    With Me.RecordsetClone
        .FindFirst "ID = " & _
        Me.cboFindRequest.Column(0)
        If Not .NoMatch Then
            Me.Bookmark = .Bookmark
            'Set detail, footer and save button visible
            Me.Detail.Visible = True
            Me.FormFooter.Visible = True
            Me.cmdSave.Visible = True
            'Set new record and cancel not visible
            Me.cmdNew.Visible = False
            Me.cmdCancel.Visible = False
            'setErr formats red borders around controls, and this is set to false, to remove any red borders
            For Each ctl In Forms!frmSoftwareRequest.Controls
                setErr ctl, False
            Next ctl
            'Set focus on first field, so find combo doesn't have focus and can be set to not visible
            Me.RequestName.SetFocus
            Me.cboFindRequest.Visible = False
            Me.Requery
            'call the after update function from above
            FKCostModelType_AfterUpdate
            'call a function to update a calculated control on form
            UpdateCostEstimate
        End If
    End With
End Sub

现在有 2 件事出了问题 - 一个是控件没有正确锁定。我使用组合查找请求,然后向下滚动到组合部分以选择成本模型。当我尝试更改该组合时,会发生第二个问题。我收到一个错误:数据已更改。在您尝试保存更改之前,另一个用户编辑了此记录并保存了更改。重新编辑记录。

呃。我确定我做错了 10 件事,但我似乎无法弄清楚是什么。这个新编辑中的第一个函数(CostModelLock)我认为问题在于我一直在执行 debug.print 等的 frm 和 ctl 调用,但没有看到我期望发生的事情。我可以提供更多信息,但不确定提供什么。非常感谢您的帮助!

【问题讨论】:

  • 尝试禁用 then 锁定和解锁 then 启用。
  • 请解释什么不是你想要的方式。还要说明这个函数是如何被调用的,以及从哪里调用的。
  • 故障排除。将您的功能减少到一行:Forms!frmRequest.BField3.Enabled = False。那样有用吗?然后从那里扩展。我们真的需要看一点调用这个函数的代码。
  • @JohnBingham:如果您只禁用,该控件将变灰。如果你也锁定,控件会正常显示。
  • @JohnBingham:“只是锁定它做同样的事情”。不,那么控件仍然可以获得焦点。 “..如果它以前是可编辑的,”谁说它是?这一切都取决于。如果你做了大量的开发工作,你会随着时间的推移找到所有四种设置的选项。

标签: ms-access vba boolean case


【解决方案1】:

如果,正如 Hans 所指出的,没有一个控件具有焦点,那么您的代码应该可以工作,所以 - 很可能 - 发生了其他事情。

作为旁注,您的代码可以简化为:

Public Function CostModelLock(LockType As String, LockOn As Boolean)

    Dim Index As Integer

    For Index = 1 to 3
        With Forms!frmRequest(LockType & "Field" & CStr(Index))
            .Locked = LockOn
            .Enabled = Not LockOn
        End With
    Next
    Forms!frmRequest.Repaint

End Function

【讨论】:

  • 有趣。该索引是选项卡索引吗?我刚刚了解了使用控件的标记属性。它允许我将控件集分组为 1 个标记,因此我可以循环遍历这些控件。最后,尝试保存或关闭表单会导致验证功能在未填写所需信息时提醒用户。对于此设置,他们需要选择一个模型,并填写该模型的所有 3 个字段。它创造了对大量代码的需求,但我喜欢任何让它尽可能光滑的机会。我将不得不玩弄你发布的内容,看看它是如何工作的。谢谢!
  • 不,这里的Index只是控件name的一部分。但你是对的;您可以将 Tag 分配给要循环的控件,然后检查 Tag,或者也可以使用 TabOrder,尽管这可能更困难,因为大多数控件都有TabOrder 分配。此外,您可以检查 ControlType 以过滤特定控件,忽略其中的名称或其他属性。
  • 是的,我将尝试保持锁定/解锁状态,并尝试将背景变灰(如果它被锁定)。我会在测试后发布!
  • 如果我想使用您说“With Forms!frmRequest(LockType & "Field" & CStr(Index)) 的部分,我想这样做,但我使用的是标签。我不确定语法。我也不确定 LockType 变量应该是什么。我会查找这个,但如果你知道,那会很有帮助。这是我目前所拥有的:
  • For Each ctr In Forms!frmRequest.Controls '查找特定标签 If ctr.Tag = TagType Then End If Next ctr TagType 将具有将传递给函数,以及用于锁定或解锁(以及是否变灰)的布尔值 true false
【解决方案2】:

我明白了!我正在回答我自己的问题,这样我就可以把我的整个代码放在这里,以防它帮助别人。我也会标记古斯塔夫的答案,因为它把我带到了这里。

首先,这是最后一个公共函数,它禁用和锁定每个将 tag 属性设置为通过 TagType 传递的值的控件,并且是文本框或组合框。

Public Function CostModelLock(TagType As String, LockOn As Boolean)
    Dim ctl As Control
    Dim bColor As String
    Dim NotLockOn

    If LockOn = True Then
        NotLockOn = False
    Else
        NotLockOn = True
    End If

    If LockOn = True Then
        bColor = RGB(192, 192, 192)
    Else
        bColor = vbWhite
    End If

    'Loop through every control on the form
    For Each ctl In Forms!frmRequest.Controls
    Debug.Print ctl.Name
        If ctl.Tag = TagType Then
        Debug.Print ctl.Tag
            If ctl.ControlType = acTextBox Or ctl.ControlType = acComboBox Then
            Debug.Print Nz(ctl.ControlType, 0)
            Debug.Print ctl.Locked
                ctl.Enabled = NotLockOn
                ctl.Locked = LockOn
                ctl.BackColor = bColor
            Debug.Print ctl.Locked
            End If
        Else
        Debug.Print ctl.Tag
        End If

    Next ctl
    Forms!frmSoftwareRequest.Repaint
End Function

我有一个多余的启用和背景颜色,但这不会伤害任何东西。我可能会删除背景颜色部分,但现在不太在意。

表单上组合的更新后现在调用一个公共函数,这样我就可以在需要的任何地方调用这个其他函数:

Public Function ActiveCostModel()
    If Nz(Forms!frmRequest.FKCostModelType.Value) <> 0 Then
        If Forms!frmRequest.FKCostModelType.Column(0) = 1 Then
            CostModelLock "ReqCostA", False
            CostModelLock "ReqCostB", True
        ElseIf Forms!frmRequest.FKCostModelType.Column(0) = 2 Then
            CostModelLock "ReqCostB", False
            CostModelLock "ReqCostA", True
        End If
    ElseIf Nz(Forms!frmRequest.FKCostModelType.Value) = 0 Then
        CostModelLock "ReqCostA", True
        CostModelLock "ReqCostB", True
    End If
    Call UpdateCostEstimate
End Function

最好的部分 --> 一切正常!非常感谢@Gustav 和其他所有人的回复和帮助!

【讨论】:

  • 太棒了!并感谢您的反馈。周末愉快。
猜你喜欢
  • 2010-12-07
  • 1970-01-01
  • 1970-01-01
  • 2016-09-26
  • 2020-09-02
  • 1970-01-01
  • 1970-01-01
  • 2022-08-22
相关资源
最近更新 更多