出现在控制源不是 PK 字段的文本框中的记录的主键
Posted
技术标签:
【中文标题】出现在控制源不是 PK 字段的文本框中的记录的主键【英文标题】:Primary Key for record appearing in textbox where Control Source is not PK field 【发布时间】:2017-08-17 16:23:09 【问题描述】:我在使用 Access 2010 数据库时遇到问题,当我移动到链接表单上的另一个控件时,新记录的主键也被添加到不相关的字段中。
我的最小数据库由一个名为Teams
的表组成。表中有四个字段:
+-----------------+-----------+-----------+--------------+
| TeamID | TeamName | CostCode | SortOrder |
+-----------------+-----------+-----------+--------------+
| AutoNumber (PK) | Text(255) | Text(255) | Long Integer |
+-----------------+-----------+-----------+--------------+
此表通过Record Source
链接到名为Edit_Teams
的表单。
表单上有三个控件:
+-----------------+-------------+-----------+------------------------------------+
| Control: | TextBox | TextBox | ComboBox |
+-----------------+-------------+-----------+------------------------------------+
| Name: | txtCostCode | txtTeamID | cmbTeamName |
| Control Source: | CostCode | TeamID | - |
| Row Source: | - | - | SELECT TeamID, TeamName FROM Teams |
+-----------------+-------------+-----------+------------------------------------+
combobox
绑定到第 1 列,Limit To List = Yes
当您在记录之间移动时,表单有一些代码可以使组合框与表单的其余部分保持同步:
Private Sub Form_Current()
If Not IsNull(Me.txtTeamID) Then
Me.cmbTeamName.Requery
Me.cmbTeamName = Me.txtTeamID
If Me.cmbTeamName <> 0 Then
'Some other code that adds stuff to a subform.
Me.Refresh
End If
Else
Me.cmbTeamName = 0
End If
End Sub
组合框有两个事件:
Private Sub cmbTeamName_AfterUpdate()
If Me.cmbTeamName = "0" Then
DoCmd.GoToRecord , , acNewRec
Else
GoToBookmark Me, "TeamID", cmbTeamName
If cmbTeamName <> 0 Then
'Some other code that adds stuff to a subform.
Me.Refresh
End If
End If
End Sub
和
Private Sub cmbTeamName_NotInList(NewData As String, Response As Integer)
With DoCmd
.SetWarnings False
If MsgBox("Add '" & NewData & "' as a new team?", vbYesNo + vbQuestion) = vbYes Then
.RunSQL "INSERT INTO Teams(TeamName, CostCode, SortOrder) " & _
"VALUES ('" & NewData & "', Null," & DCount("TeamID", "Teams") + 1 & ")"
Response = acDataErrAdded
Me.cmbTeamName = Me.cmbTeamName.ItemData(0) 'Move to an item that exists so Requery doesn't fire NotInList.
Me.Requery
GoToBookmark Me, "TeamName", NewData
Me.cmbTeamName.Requery
Me.cmbTeamName = DLookup("TeamID", "Teams", "TeamName='" & TeamName & "'")
Me.txtCostCode.SetFocus
Else
Response = acDataErrContinue
Me.cmbTeamName.Undo
End If
.SetWarnings True
End With
End Sub
在前面的过程中也使用了这个:
Public Sub GoToBookmark(frm As Form, FieldName As String, FieldValue As String)
Dim rst As DAO.Recordset
Dim rst_Type As Long
On Error GoTo ERR_HANDLE
Set rst = frm.RecordsetClone
FieldName = "[" & FieldName & "]"
Select Case rst.Fields(FieldName).Type
Case 4 'dbLong
rst.FindFirst FieldName & "=" & FieldValue
Case 10 'dbText
rst.FindFirst FieldName & "='" & FieldValue & "'"
End Select
If Not (rst.BOF And rst.EOF) Then
frm.Recordset.Bookmark = rst.Bookmark
End If
rst.Close
EXIT_PROC:
Set rst = Nothing
On Error GoTo 0
Exit Sub
ERR_HANDLE:
'Commented out so I don't have to post the DisplayError procedures.
'DisplayError Err.Number, Err.Description, "mdl_GoToBookMark.GoToBookmark()"
Resume EXIT_PROC
End Sub
问题: 当我在组合框中输入新的团队名称时,它会询问我是否要将其添加到团队列表中,然后它会添加团队并将我移动到 CostCode 文本框,如果可用,我可以在其中输入成本代码。 如果成本代码不可用,则控件应保持空白,但当我移动到另一个控件或记录(即控件失去焦点)时,该记录的主键将出现在 CostCode 文本框中,并在我更改记录时保存(失去焦点只是把它放在文本框中,它不会出现在表格中,直到记录被保存)。
【问题讨论】:
时髦的行为。我怀疑在NotInList
事件过程中做所有这些事情对于Access 来说有点太多了。注意Me.Requery
也会触发Form_Current()
,所以我想说Me.cmbTeamName
操作都是多余的。您可以将独立的示例数据库上传到文件主机吗?
我很高兴NotInList
事件中没有发生太多事情。这将是一个真正的痛苦来解决。我将再看一下Me.Requery
,尽管在GoToBookMark
调用的任一侧使用它似乎有点矫枉过正,即使第二个调用只请求控件。我会让你知道...
乍一看,我确实可以删除第一个重新查询并更改第二个以重新查询整个表单。我必须检查一下它没有损坏其他任何东西,但目前一切看起来都很好。
【参考方案1】:
您的问题在于以下行:
Response = acDataErrAdded
一旦失去焦点,此行将触发 Access 将具有焦点的字段设置为您刚刚添加的值。因为您将焦点转移到不同的领域,所以会出现这种奇怪的行为。
将其更改为 Response = acDataErrContinue
(这基本上告诉 Access 不关心您输入的内容,并让您自己处理)并且您的代码应该按预期运行。
【讨论】:
谢谢埃里克。那成功了。我终于可以摆脱最后一个不会真正影响数据库操作的烦人错误(成本代码比 PK 大得多,所以当它是错误的数字时很明显)总是需要学习新东西。跨度>以上是关于出现在控制源不是 PK 字段的文本框中的记录的主键的主要内容,如果未能解决你的问题,请参考以下文章