You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Access表单列表框AfterUpdate事件变量串扰问题求助

Access表单列表框误删记录问题

场景与问题

我有一个包含多个列表框和关联文本框的Access表单,逻辑是:选择列表框名称后触发AfterUpdate事件,查询数据库判断Eng_ID与Person_ID是否已存在于表中。存在则删除该行并插入更新记录,不存在则直接插入。

但切换列表框时,DLookup会错误使用前一个列表框的Person_ID,导致误删前一个列表框对应的记录,再插入新选择的记录。

现有代码

' Add/Remove Participant 1
Private Sub lstPar1_AfterUpdate()
    Dim n As Integer
    Dim strCriteria As String
    Dim strSQL As String
        
     With Me.lstPar1
        For n = .ListCount - 1 To 0 Step -1
            strCriteria = "Eng_ID = " & Nz(Me.Eng_ID, 0) & " And Person_ID = " & .ItemData(n)
                If .Selected(n) = False Then
                ' If a person has been deselected, then delete row from table
                If Not IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
                    strSQL = "DELETE * FROM tblEngParRole WHERE " & strCriteria
                    CurrentDb.Execute strSQL, dbFailOnError
                    
                End If
                Else
                ' If a person has been selected, then insert row into the table
                If IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
                   strSQL = "INSERT INTO tblEngParRole (Eng_ID, Person_ID, ParticipantNumber, Role)" & "VALUES(" & Me.Eng_ID & "," & .ItemData(n) & "," & 1 & ",'" & Me.txtParRole1.Value & "' )"
                    CurrentDb.Execute strSQL, dbFailOnError
                End If
            End If
        Next n
    End With
    
End Sub

' Add/Remove Participant 2

Private Sub lstPar2_AfterUpdate()
    Dim n As Integer
    Dim strCriteria As String
    Dim strSQL As String
    
    With Me.lstPar2
     For n = .ListCount - 1 To 0 Step -1
            strCriteria = "Eng_ID = " & Nz(Me.Eng_ID, 0) & " And Person_ID = " & .ItemData(n)
                If .Selected(n) = False Then
                ' If a person has been deselected, then delete row from table
                If Not IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
                    strSQL = "DELETE * FROM tblEngParRole WHERE " & strCriteria
                    CurrentDb.Execute strSQL, dbFailOnError
                End If
                Else
                ' If a person has been selected, then insert row into the table
                If IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
                    strSQL = "INSERT INTO tblEngParRole (Eng_ID, Person_ID, ParticipantNumber, Role) " & "VALUES(" & Me.Eng_ID & "," & .ItemData(n) & "," & 2 & ",'" & Me.txtParRole2.Value & "' )"
                    CurrentDb.Execute strSQL, dbFailOnError
                End If
            End If
        Next n
    End With
End Sub

示例场景

选择Daniel并输入角色后,数据库录入记录:Eng_ID=130、Person_ID=118、ParticipantNumber=1、Role=Collaborator;再选择Kristin时,系统错误使用Person_ID=118删除Daniel的记录,随后添加Kristin的记录。

解决方案

问题出在判断条件不完整:当前仅用Eng_ID和Person_ID作为判断依据,但同一个Person_ID可能对应不同的ParticipantNumber(比如参与者1和参与者2)。需要把ParticipantNumber也加入查询条件,确保只处理当前列表框对应的参与者记录。

修改后的lstPar1_AfterUpdate事件

' Add/Remove Participant 1
Private Sub lstPar1_AfterUpdate()
    Dim n As Integer
    Dim strCriteria As String
    Dim strSQL As String
        
     With Me.lstPar1
        For n = .ListCount - 1 To 0 Step -1
            ' 加入ParticipantNumber=1作为条件,限定只处理参与者1的记录
            strCriteria = "Eng_ID = " & Nz(Me.Eng_ID, 0) & " And Person_ID = " & .ItemData(n) & " And ParticipantNumber = 1"
                If .Selected(n) = False Then
                ' 删除对应参与者1的记录
                If Not IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
                    strSQL = "DELETE * FROM tblEngParRole WHERE " & strCriteria
                    CurrentDb.Execute strSQL, dbFailOnError
                    
                End If
                Else
                ' 插入参与者1的记录
                If IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
                   strSQL = "INSERT INTO tblEngParRole (Eng_ID, Person_ID, ParticipantNumber, Role)" & _
                            "VALUES(" & Me.Eng_ID & "," & .ItemData(n) & "," & 1 & ",'" & Me.txtParRole1.Value & "' )"
                    CurrentDb.Execute strSQL, dbFailOnError
                End If
            End If
        Next n
    End With
    
End Sub

修改后的lstPar2_AfterUpdate事件

' Add/Remove Participant 2
Private Sub lstPar2_AfterUpdate()
    Dim n As Integer
    Dim strCriteria As String
    Dim strSQL As String
    
    With Me.lstPar2
     For n = .ListCount - 1 To 0 Step -1
            ' 加入ParticipantNumber=2作为条件,限定只处理参与者2的记录
            strCriteria = "Eng_ID = " & Nz(Me.Eng_ID, 0) & " And Person_ID = " & .ItemData(n) & " And ParticipantNumber = 2"
                If .Selected(n) = False Then
                ' 删除对应参与者2的记录
                If Not IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
                    strSQL = "DELETE * FROM tblEngParRole WHERE " & strCriteria
                    CurrentDb.Execute strSQL, dbFailOnError
                End If
                Else
                ' 插入参与者2的记录
                If IsNull(DLookup("Eng_ID", "tblEngParRole", strCriteria)) Then
                    strSQL = "INSERT INTO tblEngParRole (Eng_ID, Person_ID, ParticipantNumber, Role) " & _
                             "VALUES(" & Me.Eng_ID & "," & .ItemData(n) & "," & 2 & ",'" & Me.txtParRole2.Value & "' )"
                    CurrentDb.Execute strSQL, dbFailOnError
                End If
            End If
        Next n
    End With
End Sub

额外优化建议

  • 避免直接拼接SQL字符串,防止SQL注入风险,可使用参数化查询:
    ' 示例:参数化插入
    Dim qdf As QueryDef
    Set qdf = CurrentDb.CreateQueryDef("", _
        "INSERT INTO tblEngParRole (Eng_ID, Person_ID, ParticipantNumber, Role) VALUES (@EngID, @PersonID, @PartNum, @Role)")
    qdf.Parameters("@EngID") = Me.Eng_ID
    qdf.Parameters("@PersonID") = .ItemData(n)
    qdf.Parameters("@PartNum") = 1
    qdf.Parameters("@Role") = Me.txtParRole1.Value
    qdf.Execute dbFailOnError
    Set qdf = Nothing
    
  • 将重复逻辑封装成通用函数,减少代码冗余,比如创建一个UpdateParticipant函数,接收列表框控件、参与者编号、角色文本框作为参数。

内容的提问来源于stack exchange,提问作者Bruce Sorge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 02:35:22