控制子表单记录和选项卡控制页面?

Posted

技术标签:

【中文标题】控制子表单记录和选项卡控制页面?【英文标题】:Controlling Subform Records and Tab Control Pages? 【发布时间】:2017-08-16 18:45:20 【问题描述】:

我有一个“联系人”表格。这有一个带有子表单的选项卡控件。其中一页有一个连续的要求子表格。这 12 种需求类型中有 9 种具有相应的标签页和子表单。我使用公共功能来检查页面的可见性,以便确保唯一可见的页面是已设置为具有要求的页面。

我需要能够控制的其他事情如下:

    如果有人删除了需求,我必须检查需求联系人 - 需求详细信息表中的任何详细记录。用户可以添加联系人要求。这将显示该标签页和子表单,但用户可能永远不会填写该要求的任何详细信息。因此,代码会在该要求中查找子记录。如果有,则警告用户并要求确认他们要删除详细记录。如果是,则将其删除,然后删除联系需求记录本身。如果没有详细记录,则直接删除该联系需求记录。

    如果有人要添加新需求,在添加新记录之前,我需要检查此联系人记录,是否有相同需求类型的联系人需求记录。如果是这样,告诉他们他们不能这样做,然后退出。

这里是用于根据联系人需求表中的需求类型检查当前联系人页面可见性的代码。为清楚起见,我在 tblReqType 表中添加了列。它有 ID 和 txtRequirementType。它还有txtRequirementPage和txtRequirementTable,如果需求类型有对应的页和表要标识,则有页和源表的名称。

Public Function ShowReqs(MCID As Integer)
    Dim db As DAO.Database
    Dim ReqPages As String
    Dim ShowReqPages As DAO.Recordset
    Dim IsReq As Integer
    Dim showpg As Variant
    Dim reqrec As Integer
    Dim ctl As Control

    If Forms!frmMContacts.Detail.Visible = True Then
        Forms!frmMContacts.frmMContacts_SubRequirements.Form.Dirty = False

        Set db = CurrentDb

        ReqPages = "SELECT tblReqType.ID, tblReqType.txtRequirementPage, tblReqType.txtRequirementTable " & _
                        "FROM tblReqType " & _
                        "WHERE tblReqType.txtRequirementPage is not null;"

        Set ShowReqPages = db.OpenRecordset(ReqPages, dbOpenDynaset, dbSeeChanges)

        Forms!frmMContacts.Painting = False

        Do While Not ShowReqPages.EOF
            IsReq = DCount("*", "tblMContactRequirements", "FKMC = " & Nz(Forms!frmMContacts.ID, 0) & " and FKRequirementType = " & ShowReqPages.Fields("ID"))
            If IsReq = 0 Then
                showpg = False
            Else
                showpg = True
            End If
            Forms!frmMContacts.tbMContactsubs.Pages(ShowReqPages.Fields("txtRequirementPage")).Visible = showpg
            For Each ctl In Forms!frmMContacts.tbMContactsubs.Pages(ShowReqPages.Fields("txtRequirementPage")).Controls
                With ctl
                    Select Case .ControlType
                    Case acSubform
                        ctl.Form.Requery
                    End Select
                End With
            Next ctl

        ShowReqPages.MoveNext
        Loop

        Forms!frmMContacts.Painting = True
        Forms!frmMContacts.Repaint
        Set db = Nothing
        Set ShowReqPages = Nothing
    End If
End Function

这似乎可行,但是当我试图为相同的联系人 ID 添加重复的需求类型时,它会妨碍我。我需要在它通过 SQL 中的表之前抓住它。这是因为我在 tblMContactRequirements 表上为 FKMC(联系人 ID)和 FKRequirementType 列放置了一个索引,以使这两个列在一起是唯一的。它抛出了一个关于索引的讨厌的 odbc 消息,我想提前,检查潜在的重复,如果它会导致重复/触发索引错误,则将其退出。

在子需求表单中,我将以下内容放入 Before_Update,然后放入 Before_Insert。无论哪种方式,我都会遇到奇怪的问题。很难指出它们,因为我不知道是什么导致了发生的事情。我解决了一件事情,然后又出现了另一个问题。

这是代码,旨在捕捉骗子:

Private Sub Form_BeforeInsert(Cancel As Integer)
Dim rst As DAO.Recordset
Dim reqrec As Integer
DoCmd.SetWarnings True
Set rst = Me.RecordsetClone
rst.FindFirst "[FKRequirementType] = " & Me.FKRequirementType & " AND [FKMC] = " & Me.Parent!ID
If Not rst.NoMatch Then
    MsgBox "This requirement has already been added! ", vbOKOnly, "Requirements Shouldn't be Added Twice."
    Me.Undo
    BeforeResult = 1
Else
    BeforeResult = 0
End If
rst.Close
Me.Dirty = False

我尝试将它放在需求类型组合控件的更改中:

Private Sub FKRequirementType_Change()
Form_BeforeInsert (0)
If BeforeResult = 1 Then
Exit Sub
Else
    Form_AfterUpdate
End If
End Sub

我尝试将其放入表单更新后:

Private Sub Form_AfterUpdate()
Dim FKMC As Integer
FKMC = Nz(Me.Parent!ID, 0)
Call ShowReqs(FKMC)
End Sub

我不知道我是否过度编码,把东西放在错误的地方,还是什么。

如果有人能帮我解决这个问题,我会很感激另一双眼睛!

【问题讨论】:

Form_BeforeInsert() 内而不是调用 Me.Undo,而是设置 Cancel = True 并让表单的内置行为按设计工作。不要直接从其他过程调用 Form_BeforeInsert(),而是使用公共代码创建一个新的子过程并调用它。然后,您可以更好地精确控制不同条件的处理方式。这是一个很好的模式,可以帮助避免尝试为所有可能的场景编写事件处理程序。 Form_AfterUpdate() 等其他事件处理程序也是如此。这可能会减少一些“奇怪的行为”。 “碍事”是什么意思?从描述来看,能够在执行其他操作之前检查重复项似乎是完全合理的,但尚不清楚为什么一个函数会阻止代码检查其他条件。如果您无法准确描述“奇怪”之外的问题,则可能需要禁用代码并一次处理一个方面。放置 Debug.Print 调用以跟踪执行顺序、记录表单和控件属性等。 恕我直言,我提供了很多代码和解释。我最终弄清楚了。我会尽快发布答案。 很高兴您找到了解决方案!但出于同样的尊重,提供大量包含多个需求列表的代码以及模糊的问题描述超出了 Stack Overflow 上预期的问题类型。还有其他论坛,这是常态,但 SO 是有目的的不同。请参阅this help page 上关于调试帮助的#1,以获取有关编写更简洁、更有针对性的问题的提示。 【参考方案1】:

我想出了这个问题的答案。这是现在组合的更改事件:

Private Sub FKRequirementType_Change()
Dim i As Integer
    If Nz(Me.FKRequirementType) <> 0 Then
        i = DCount("*", "tblMContactRequirements", "FKMC=" & Me.Parent!ID & " And FKRequirementType=" & Me.FKRequirementType.Value)
        If (i > 0) Then
            MsgBox "This contact already has a " & Me.FKRequirementType.Column(1) & " requirement.", vbOKOnly + vbExclamation, "No Duplicates!"
            Me.Undo
        Else
            Call ShowReqs(FKMC)
        End If
    End If
End Sub

位置,位置,位置。在哪里调用检查正在运行的过程真的很重要。

感谢大家的回复和帮助!

【讨论】:

我很高兴这对你有用,它可能已经足够了。但与我之前提到的类似,使用 FKRequirementType_BeforeUpdate 事件并设置 Cancel = True 可能更健壮。 Access 中的事件模型至少可以说是古怪的,有时 Change 事件会发生奇怪的行为,这取决于用户是使用鼠标选择还是使用键盘选择还是使用剪切和粘贴等 - 一些随机组合可能仍允许重复条目。在 Cancel = True 的 Before_Update 和 Before_Insert 形式中添加类似的代码仍然可以很好地防止坏数据。 谢谢。我肯定和你在一起。我的另一个担忧是,访问在捕获 ODBC 错误方面也很糟糕。在我控制好我的庞大待办事项清单后,我可能会重新审视这个。目前,它正在工作。我绝对期待在未来改进它的编写方式。

以上是关于控制子表单记录和选项卡控制页面?的主要内容,如果未能解决你的问题,请参考以下文章

管理多个选项卡的 webapp 会话数据/控制器流

如何通过 VBA 设置访问选项卡控件的页面名称

Access 2007 中的选项卡控件之外的选项卡

Access 2007 使用选项卡将多个子表单链接到主表单的最佳方式

切换选项卡时删除所有子视图控制器并移至父视图控制器 IOS 目标 c

mfc 选项卡控制切换选项卡