Me.Dirty移动当前选择的记录

时间:2014-12-12 19:45:00

标签: sql vba ms-access

我有一个Access 2007表单让我头疼。

我有一个记录列表,从一个组合框开始挑选一家公司,然后是一系列复选框来表明公司的角色。

Screenshot

如果用户需要添加新公司,他们会从组合框中选择公司名称,然后单击指示公司正在扮演什么角色的复选框。选中该复选框后,表单将跟随以下代码以显示捕获其他信息的弹出窗口:

Private Sub chkOperationsAndMaintenance_AfterUpdate()
    'DoCmd.RunCommand acCmdSaveRecord'
    If Me.Dirty Then Me.Dirty = False
    If chkOperationsAndMaintenance.Value = True Then
        DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
        Me.Requery
    End If
End Sub

此代码将保存CompanyProject表上的记录以创建行。然后它拉出CompanyProjectID(CompanyProject表的PK),以便它知道要为弹出窗口提供哪个ID。

我遇到的问题是在Me.Dirty行(以及上面注释掉的acCmdSaveRecord)上,整个表单保存并刷新,将所选行移动到第一个记录(在本例中为“Gamesa” “)而不是新输入的记录。因此,随后的弹出窗口输入第一条记录的CompanyProjectID而不是新输入的记录,它还从第一条记录而不是用户正在工作的记录中读取复选框的“已检查”状态。

我修改了代码看起来像这样:

Private Sub chkOperationsAndMaintenance_AfterUpdate()
    Dim CPID As Long
    Dim CID As Long
    Dim rs As Recordset
    Set rs = Me.RecordsetClone
    CID = Me.CompanyID
    'DoCmd.RunCommand acCmdSaveRecord'
    If Me.Dirty Then Me.Dirty = False
    CPID = DLookup("MAX(CompanyProjectID)", "CompanyProject", "cpProjectID = " & Me.cpProjectID & _
        " AND CompanyID = " & CID)
    rs.Find "[CompanyProjectID] = " & CPID
    Me.Bookmark = rs.Bookmark
    If chkOperationsAndMaintenance.Value = True Then
        DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
        Me.Requery
    End If
End Sub

这些改动的想法是我们将从父表单(“cpProjectID”)获取FK并从组合框中获取选择的CompanyID,然后保存记录。保存记录后,我们已经存储了CompanyProjectID,因此rs.Find和Me.Bookmark行将选择与该CompanyProjectID匹配的记录。

这有时会起作用,有时则不起作用。一般不会。在这种情况下,我刷新了父表单和当前表单,并尝试添加新公司,然后单击“所有者”复选框(使用与上面相同的代码,只是一个不同的复选框ID)来查看错误的书签行:

Screenshot2

此时,我不知道该怎么办。如果我不保存记录(通过acCmdSaveRecord或Me.Dirty = False),那么我没有将CompanyProjectID作为后续弹出窗口的输入参数发送,但如果我确实保存了记录,那么表单会更改记录和错误的参数被发送,并且读取错误的复选框的检查状态。我不能只使用任意索引(例如acNewRec),因为用户可能需要编辑现有行而不是添加新行。

我已经尝试过这篇文章中的方法:MS Access how to Update current row, move to next record, not first,但是查找/书签并不是一直有效。

编辑(2014年12月15日)

我最终使用以下VBA代码:

Private Sub chkOperationsAndMaintenance_AfterUpdate()
    Dim CPID As Long
    Dim CID As Long
    Dim rs As Recordset
    Set rs = Me.RecordsetClone
    CID = Me.CompanyID
    If Me.Dirty Then Me.Dirty = False
    CPID = DLookup("MAX(CompanyProjectID)", "CompanyProject", "cpProjectID = " & Me.cpProjectID & _
        " AND CompanyID = " & CID)
    Do While Me.CompanyProjectID <> CPID
        If Me.CurrentRecord < Me.Recordset.RecordCount Then
            DoCmd.GoToRecord , , acNext
        Else
            DoCmd.GoToRecord , , acFirst
        End If
    Loop
    If chkOperationsAndMaintenance.Value = True Then
        DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
        Me.Requery
    End If
End Sub

我觉得必须有一个更好的答案,但这似乎现在正在发挥作用。我现在让我的最终用户/实验室老鼠对它进行测试,所以如果这样做,我会将此标记完整。我仍然认为必须有一个更好的解决方案,但目前,此解决方案能够捕获传递给弹出窗口的必需ID,并在捕获此ID后选择适当的行。

2 个答案:

答案 0 :(得分:1)

您是否考虑过保存当前位置 - 例如Me.CurrentRecord,然后在保存重新定位到所需记录之后。例如,您可以添加“之前”或“之后”插入以保存位置,然后再重新定位。请参阅以下内容:

Option Compare Database
Option Explicit

Dim lCurRec As Long

Private Sub Form_AfterInsert()
    lCurRec = Me.CurrentRecord
    Debug.Print "After Insert, Current: " & Me.CurrentRecord
End Sub

<<< YOUR SUB>>>
DoCmd.GoToRecord acDataForm, Me.Name, acGoTo, lCurRec

答案 1 :(得分:1)

此代码在添加新记录时以及编辑现有记录时都有效:

  Private Sub chkOperationsAndMaintenance_AfterUpdate()
  Dim c As Long
  Me.Dirty = False          
  If chkOperationsAndMaintenance Then
      DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
      c = Me.CurrentRecord                 
      Me.Requery                           
      DoCmd.GoToRecord , , acGoTo, c       
  End If
  End Sub

我猜你的弹出窗体会做一些特定于Operations&amp; amp;维护,并且不会更改主窗体上任何复选框的值。如果是这种情况,则根本不需要Requery,代码可以简化:

  Private Sub chkOperationsAndMaintenance_AfterUpdate()
  Me.Dirty = False
  If chkOperationsAndMaintenance Then
      DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
  End If
  End Sub
相关问题