Forms 如何编辑要以交互方式选择的VBA表单中的记录?

Forms 如何编辑要以交互方式选择的VBA表单中的记录?,forms,ms-access,vba,editing,Forms,Ms Access,Vba,Editing,我在MS Access 2003数据库中有一组组合框,它们都绑定到单个表中的字段。但是,它们允许您选择的数据不是来自该表,而是来自其他各种表。这对于记录创建故事来说很好,但现在我希望能够追溯编辑记录。问题是我不知道如何在不编写一堆自定义代码的情况下重新填充表单元素 我最初的倾向是提供一个组合框,将您的选择限制为记录ID,然后执行自定义查询,并使用它在所有不同的表单元素中设置所选值。但是,我觉得我应该能够做一些简单的事情,比如DoCmd.GoToRecord、、ID,表单应该可以重新填充。我并不反

我在MS Access 2003数据库中有一组组合框,它们都绑定到单个表中的字段。但是,它们允许您选择的数据不是来自该表,而是来自其他各种表。这对于记录创建故事来说很好,但现在我希望能够追溯编辑记录。问题是我不知道如何在不编写一堆自定义代码的情况下重新填充表单元素


我最初的倾向是提供一个组合框,将您的选择限制为记录ID,然后执行自定义查询,并使用它在所有不同的表单元素中设置所选值。但是,我觉得我应该能够做一些简单的事情,比如
DoCmd.GoToRecord、、ID
,表单应该可以重新填充。我并不反对做这些繁忙的工作,但我确信我在VBA和Access方面的知识相对较少,只是缺少了一些东西。

我想您已经为每个组合框设置了行源。只要您没有将组合框限制在该列表中;它应该显示您在该列中存储的内容

但是,如果组合框更改了每行的列表,则可以在记录的OnCurrent事件或字段的GotFocus事件中执行类似操作:

Me.combo_box_name.Requery 

在重读了你的问题之后,我想我看到了你想要实现的目标。您使用
GotoRecord
的方法是正确的,尽管在本例中我可能会使用
OpenForm
,因为它有一个
WhereCondition
属性,允许您使用SQL精确地指定要打开的记录。听起来您想在表单中实现“跳转到记录”类型的功能,用户从列表中选择记录ID,表单更改以显示所选记录

一种可能性是每次用户在组合框中选择一个项目时切换到新记录。您可以在组合框的
单击事件中处理此问题

我将使用一个简单的示例:假设您有一个
Students
表和一个
StudentForm
用于查看/编辑
Students
表中的记录。
StudentForm
有一个组合框
cboStudentID
,它通过
RowSource
属性绑定到
Students.ID
列。在组合框中选择学生ID时,
StudentsForm
将切换显示相应的学生记录

在组合框的
单击
事件处理程序中,您可以使用以下内容对“跳转到录制”功能进行编码:

Private Sub cboStudentID_Click() 
    Dim recordID As Long
    'The ItemData property will return the value of the bound'
    'column at the specified index.'
    recordID = cboStudentID.ItemData(cboStudentID.ListIndex)
    'Jump to the record. This assumes we want to use the same form.'
    'You can change the form name if you want to open a different form when'
    'the user selects an ID from the ComboBox.'
    DoCmd.OpenForm "StudentForm", WhereCondition:="Student.ID=" & recordID
End Sub
正如David W.Fenton在评论中指出的,您可以缩短以下行:

recordID = cboStudentID.ItemData(cboStudentID.ListIndex)
为此:

recordID = Me!cboStudentID
或者只是:

recordID = cboStudentID
因为在这种情况下,组合框的默认值将是当前
列表索引中绑定列的值。在这种情况下,您可以完全删除
recordID
,并对
单击事件进行编码,如下所示:

Private Sub cboStudentID_Click() 
    DoCmd.OpenForm "StudentForm", WhereCondition:="Student.ID=" & cboStudentID
End Sub

为了补充这一点,我将提供两种方法,一种是推荐的,另一种不是

方法1:如果已将表单绑定到整个数据表(这是不推荐的方法),则可以使用组合框向导导航到请求的记录,但我不建议在Access的最新版本中使用它:

a。它不允许您在创建代码之前正确命名组合框

b。代码是错误的

以下是我刚刚在测试数据库中生成的代码:

Dim rs As Object

Set rs = Me.Recordset.Clone
rs.FindFirst "[InventoryID] = " & Str(Nz(Me![Combo2], 0))
If Not rs.EOF Then Me.Bookmark = rs.Bookmark
这在很多方面都是错误的,这真是了不起。代码应该是这样的:

With Me.RecordsetClone
  .FindFirst "[ID]=" & Me!cmbMyComboBox
  If Not .NoMatch Then
     If Me.Dirty Then Me.Dirty = False
     Me.Bookmark = .Bookmark
  Else
     MsgBox "Not Found!"
  End If
End With
如果RecordsetClone已存在,则无需克隆窗体的记录集

当您可以直接使用预先存在的对象时,没有理由使用对象变量

在离开记录之前需要检查脏记录,因为如果不强制保存,保存过程中的错误可能会导致数据丢失

但更好的方法是:

方法2:使用组合框更改窗体的底层记录源

组合框的AfterUpdate事件如下所示:

If Not IsNull(Me!cmbMyComboBox) Then
   Me.Recordsource = Me.Recordsource & " WHERE [ID]=" & Me!cmbMyComboBox
End If
现在,这只在第一次起作用,就像在第二次重置Recordsource时一样,您会得到两个WHERE子句,这是不好的。有两种方法:

a。假设窗体在没有WHERE子句的情况下打开,则将打开记录源值存储在窗体的OnLoad事件中的模块级变量中:

   Private Sub Form_Load()
     strRecordsource = Left(Me.Recordsource,Len(Me.Recordsource)-1)
   End Sub
在模块级,相应地定义strRecordsource:

   Dim strRecordsource As String
然后在组合框的AfterUpdate事件中,您有以下内容:

   Me.Recordsource = strRecordsource & " WHERE [ID]=" & Me!cmbMyComboBox

现在,如果您的表单以已定义的WHERE子句打开,它会变得更复杂,但我不会深入讨论,并将其作为练习留给读者,让读者知道最佳方法是什么。

这个问题令人困惑,如果您有一个带有标准组合的标准表单,这里就没有什么可做的了,它应该可以正常工作。您是否正在尝试更新每个组合框中的项目,因为它们在表单打开后发生了更改?如果ID列是绑定列(这与组合框是否绑定无关,即,是否有控件源),则组合框的默认值是ID,无需使用ItemData。如果您需要绑定列以外的内容,ItemData就是一张票证。谢谢,David。我编辑了我的答案,以反映在本例中它们是等效的。发现了一个小的打字错误。我认为第二个示例中“With Me.RecordsetClone”后面的“rs.FindFirst…”行应该是“.FindFirst…”哦,还有+1。我不是一个访问大师,我不想直接修改Recordsource。我觉得比DoCmd优雅多了。也许只是我自己,事实上我并不真正做Access编程,但诉诸DoCmd对我来说通常感觉像是一个黑客(也就是说,通常有更好的方法)。谢谢你的打字错误——现在已经修复了。