当错误再次出现时,错误处理不起作用

问题描述 投票:3回答:3

逻辑:

  • 用户。按下按钮;
  • 代码。创建“Recordset”“rstStud”(学生)和“rstGroupStud”(学生组);
  • 代码。周期。列举“rstStud”; 代码。添加“rstGroupStud”条目; 代码。如果记录存在,请转到循环中的下一条记录; 代码。如果条目是新的,请在“rstGroupStud”中添加条目; 精华:只需点击一下按钮 - 添加一个唯一条目。

问题。 当循环过去了! StudentName =“学生姓名2”在“.Update”行中我收到错误。 错误: “由于索引,主键或关系中的重复值而无法进行更改。更改包含重复值的一个或多个字段中的数据会删除索引或通过允许重复值覆盖它,然后重试。”

换句话说,第一次错误处理程序正常工作,当我重新启动时,我收到一个错误。

题。 如何根据描述的逻辑使代码工作?

Private Sub btnAddRecord_Click()
    Dim nameStud As String

    Dim rstStud As DAO.Recordset   '
    Dim rstGroupStud As DAO.Recordset '

    Set rstStud = CurrentDb.OpenRecordset("tbl_02_Students", dbOpenSnapshot)  '
    Set rstGroupStud = CurrentDb.OpenRecordset("tbl_03_GruopsStudents", dbOpenDynaset)  '

    ' *** rstStud
    With rstStud
        Do Until .EOF = True
            nameStud = !nameStud

            On Error GoTo errend
            ' *** rstGroupStud
            With rstGroupStud
                .AddNew

                !idGroup = Me.id_GroupFrm
                !nameStud = nameStud
                ' nameStud
                .Update
            End With
            rstGroupStud.Close
            Me.frm_03_GruopsStudents_tbl.Requery

            Exit Sub
errend:
            .MoveNext
        Loop
    End With

    On Error Resume Next
    rstStud.Close
    Set rstStud = Nothing
End Sub

enter image description here enter image description here enter image description here enter image description here

Update_1 文件 - link

vba ms-access access-vba
3个回答
3
投票

你需要解决执行路径;正常和错误执行状态交织在一起,这就是为什么无法处理超出第一个错误的错误的原因。

Private Sub btnAddRecord_Click()
    Dim nameStud As String

    Dim rstStud As DAO.Recordset   '
    Dim rstGroupStud As DAO.Recordset '

    Set rstStud = CurrentDb.OpenRecordset("tbl_02_Students", dbOpenSnapshot)  '
    Set rstGroupStud = CurrentDb.OpenRecordset("tbl_03_GruopsStudents", dbOpenDynaset)  '

    ' *** rstStud
    With rstStud
        Do Until .EOF = True
            On Error GoTo ErrHandler
            nameStud = !nameStud

            ' *** rstGroupStud
            With rstGroupStud
                .AddNew

                !idGroup = Me.id_GroupFrm
                !nameStud = nameStud
                ' nameStud
                .Update
            End With
            rstGroupStud.Close
            Me.frm_03_GruopsStudents_tbl.Requery

            Exit Do
TryNext:
            On Error Resume Next
            .MoveNext
            If Err.Number <> 0 Then Exit Do
            On Error GoTo 0
        Loop
    End With

    On Error Resume Next
    rstStud.Close
    Set rstStud = Nothing
    On Error GoTo 0
    Exit Sub

ErrHandler:
    Resume TryNext
End Sub

这样ErrHandler只能在错误状态下运行; TryNext在“快乐的路径”中运行,并且Exit Do突破循环(但不是在程序之外),因此清理代码可以运行任何结果。


1
投票

不要在VBA中这样做。请在查询中执行此操作。

例如,您可以这样做:

创建名为qryAssignStudentsToGroup的查询:

PARAMETERS id_GroupFrm INT;
INSERT INTO tbl_03_GruopsStudents (idGroup, nameStud)
SELECT id_GroupFrm, nameStud
FROM tbl_02_Students AS s
WHERE NOT EXISTS (
  SELECT NULL
  FROM tbl_03_GruopsStudents AS g
  WHERE s.nameStud = g.nameStud
    AND g.idGroup = id_GroupFrm
);

然后您的代码变为:

Private Sub btnAddRecord_Click()
  With CurrentDb.QueryDefs("qryAssignStudentsToGroup")
    .Parameters("id_GroupFrm") = Me.id_GroupFrm
    .Execute
  End With
  Me.frm_03_GruopsStudents_tbl.Requery
End Sub

这为同样的事情提供了更少的代码,并且只需过滤掉行就可以消除错误处理的复杂性。更重要的是,您执行一次批量更新,而不是针对您触摸的每一行。这充分利用了数据库引擎的强大功能。使用DAO.Recordset在循环中执行操作很方便,但这是一行一行的编程。你真的想要了解基于集合的编程。


1
投票

您必须调用Err.Clear来重置错误状态

errend:
    Err.Clear
    .MoveNext

我会在循环后调用Me.frm_03_GruopsStudents_tbl.Requery。一直没有重新征服形式的意义。

但跳转到另一个常规代码部分而不是去错误处理程序不是处理错误的常用方法。为了解决在MoveNext上处理错误的可能性,请更改以下代码:

Private Sub btnAddRecord_Click()
    Dim nameStud As String

    Dim rstStud As DAO.Recordset
    Dim rstGroupStud As DAO.Recordset

    Set rstStud = CurrentDb.OpenRecordset("tbl_02_Students", dbOpenSnapshot)
    Set rstGroupStud = CurrentDb.OpenRecordset("tbl_03_GruopsStudents", dbOpenDynaset)

    ' *** rstStud
    With rstStud
        Do Until .EOF = True
            nameStud = !nameStud

            On Error GoTo UpdateError
            ' *** rstGroupStud
            With rstGroupStud
                .AddNew

                !idGroup = Me.id_GroupFrm
                !nameStud = nameStud
                ' nameStud
                .Update
            End With
            rstGroupStud.Close
            Me.frm_03_GruopsStudents_tbl.Requery

            Exit Sub
continue_loop:
            On Error GoTo MoveNextError
            .MoveNext
        Loop
    End With

CleanUp:
    On Error Resume Next
    rstStud.Close
    Set rstStud = Nothing
    Exit Sub

UpdateError:
    Resume continue_loop

MoveNextError:
    MsgBox Err.Description
    Resume CleanUp
End Sub

这种模式是可扩展的。您可以根据需要添加任意数量的错误处理程序。

© www.soinside.com 2019 - 2024. All rights reserved.