MS Access:查找排除已选择的值;在记录输入完成之前检查唯一键

时间:2017-02-08 21:40:56

标签: ms-access access-vba duplicates

我目前正在努力为数据表或表单视图中的表单设置验证规则,这些规则会在转到记录中的另一个字段或完全转到另一个记录时立即触发。

我的表单旨在将记录添加到一个目标表,其中主键列需要与源表的任何记录中的特定字段的值匹配。表单(和目标表)中的其余字段用于一般用户输入(一些DateTime字段,一些文本,一些十进制)。

当用户在选择另一个字段或记录后尝试立即自由输入不在列表中的值时,我可以使Access显示标准错误对话框。显示的错误是

  

您输入的文字不是列表中的项目。
  从列表中选择一个项目,或输入与列出的项目之一匹配的文本"

如果我重新选择已经选择的查找值并转到下一条记录,我会得到

  

您向表请求的更改未成功,因为它们会在索引,主键或关系中创建重复值。更改包含重复数据的字段或字段中的数据,删除索引或重新定义索引以允许重复条目,然后重试。

但是,如果转到同一记录中的其他字段,我会立即显示该错误(或类似信息)。换句话说,我希望它告诉我它&# 39;在允许用户填写表格或表格中当前记录的其余部分之前,重复。

我希望将选择列表限制为以前未出现在目标表中的值。显然,如果编辑已经创建的条目,您应该能够保留之前的值(即该值不会从下拉列表中排除)。

或者,如果其他有效值重复,则会出现一个选择对话框。

  

重复值
  您已经使用过该值。您要更改此记录还是之前输入的记录   ⪡这一个⪢<上一页>

如果&#34;上一页&#34;如果选中,它将跳转到指定记录中的相同字段,提供重新选择的下拉列表(一旦完成,将跳回到&#34;当前&#34;记录并自动选择临时重复的值。< / p>

我将使用我的表格设计详细信息编辑此帖子,以及表单的源设置。

1 个答案:

答案 0 :(得分:0)

在VBA中解决了这个问题。

Private Sub MyControl_AfterUpdate()
    newval = Me.MyControl.Value
    oldval = Me.MyControl.OldValue
    If newval = oldval Then Exit Sub ' everything's okay
    Dim rs As Object
    Set rs = Me.Form.Recordset
    whereclause = "MyControl = '" & newval & "'"
    qry = "SELECT COUNT(*) as c FROM MyQuery WHERE " & whereclause
    qrs = CurrentDb.OpenRecordset(qry)
    If qrs.Count = 1 Then cnt = qrs(0).Value
    If cnt >= 1 Then
        selval = MsgBox("Would you like to keep your selection for this record?" & vbCrLf & "[yes = change previous record's MyField; no = change MyField for this record]", vbYesNo Or VbMsgBoxStyle.vbExclamation Or vbSystemModal Or vbDefaultButton2 Or vbMsgBoxSetForeground, "Duplicate MyField selection encountered")
        If selval = vbYes Then
            ' set focus to the other entry, preserving selection here
            thissel = Me.MyControl.ListIndex
            Me.MyControl.Value = "temp" ' if a string is okay & so we can jump away from this record
            thisloc = Me.Form.CurrentRecord ' record number
            rs.Findfirst (whereclause)
            thatloc = Me.Form.CurrentRecord
            Debug.Print (thisloc & "now  ;  was" & thatloc)
            Me.MyControl.Value = "invalid"
            DoCmd.GoToRecord , , acGoTo, thisloc  ' jump to the new row
            Me.MyControl.Value = newval
            DoCmd.GoToRecord , , acGoTo, thatloc  ' jump to the one to change
            If thissel <= 0 Then thissel = 1 ' may not be useful, given the error handling below
            On Error Resume Next
            Me.MyControl.ListIndex = thissel - 1
            On Error GoTo 0
            Me.MyControl.Dropdown
        ElseIf selval = vbNo Then
            Me.MyControl.Value = Me.MyControl.OldValue
            Me.MyControl.Undo ' for some reason this doesn't clear the "dirty" bit, resulting in the edit pencil showing up for the row.
            Me.MyControl.SetFocus
        End If
    Else
        Debug.Print ("There were no matches! Das ist gut")
    End If
End Sub

剩余问题

  1. 从对话框中选择“是”,然后点击转义将无效的“无效”字符串放入框中,这忽略了将最终选择限制为列表中的一个要求(即限制为列表= 1 < / em>的)。理想情况下,这将“回滚”两行。
  2. 也许我应该将其更改为OnExit事件,以便在我离开单元格之前不会触发它?不确定主要密钥违规是否会在此触发之前发生。 OnChange过于频繁地触发(每次你向下箭头浏览列表)。