PAYATHON 2026

Access 2016 如何在窗体打开后选中数据表子窗体记录?

数据阿明

结论

在 Access 中,Form_Load 和 Form_Current 执行时,窗体和子窗体的初始化、焦点安排可能还未完成。此时调用 RunCommand acCmdSelectRecord,记录可能会短暂显示为选中,之后又因焦点切换而取消选中状态。

可以用一次性 Form_Timer 处理这个时序问题:窗体加载时先初始化组合框、重新查询并定位记录;随后由计时器将焦点移到数据表子窗体,再选择当前记录。计时器执行后立即关闭。

调整代码

在主窗体模块中设置一次性计时器,并将最终的焦点设置和选中操作放入 Form_Timer:

Private Sub Form_Load()
    Me.TimerInterval = 1

    ' 初始化组合框并筛选子窗体记录
    Me.cboSeries = Me.cboSeries.ItemData(0)

    Dim rs As DAO.Recordset
    Set rs = Me.RecordsetClone
    rs.FindFirst "[SeriesID] = " & Str(Nz(Me.cboSeries, 0))
    If Not rs.NoMatch Then Me.Bookmark = rs.Bookmark
    rs.Close
    Set rs = Nothing

    Me.frmEps.Form.Requery

    ' 将数据表子窗体定位到第一条未观看记录
    Dim rs2 As DAO.Recordset
    Set rs2 = Me.frmEps.Form.RecordsetClone
    rs2.FindFirst "[Watched] = False"
    If Not rs2.NoMatch Then Me.frmEps.Form.Bookmark = rs2.Bookmark
    rs2.Close
    Set rs2 = Nothing
End Sub

Private Sub Form_Timer()
    Me.TimerInterval = 0

    Me.frmEps.SetFocus
    Me.frmEps.Form.SeasonNumber.SetFocus
    DoCmd.RunCommand acCmdSelectRecord
End Sub

这里假设 frmEps 是主窗体上子窗体控件的名称,SeasonNumber 是数据表子窗体中的控件名称。实际名称不同的话,请替换为对应名称。示例使用 DAO.Recordset;如果项目没有引用 DAO,需根据当前 Access 环境确认相应的引用设置。

原代码用 EOF 判断 FindFirst 是否找到记录。对于 RecordsetClone.FindFirst,用 NoMatch 判断会更直接。没有匹配记录时,代码会跳过 Bookmark 赋值。如果组合框可能为空,也要确认初始化代码不会在没有项目时访问 ItemData(0)。

为什么不建议只把代码移到另一个事件

Form_Current 可能在记录位置变化时多次触发,而且之后仍可能发生焦点切换。Form_Activate 可用于处理窗体获得焦点时的逻辑,但如果启动过程中还会调整焦点,只改用 Form_Activate 未必能解决问题。一次性计时器会在加载流程之后执行选择操作,能对应这个时序问题。

如果改用 Form_Activate,至少应增加只执行一次的标记,并确认窗口中的焦点切换顺序后再验证结果。否则,窗体再次激活时可能重复选中记录,或覆盖用户后来选择的记录。当前的一次性 Timer 已能稳定达到预期,继续使用即可。

注意事项

acCmdSelectRecord 作用于当前有焦点的窗体或控件上下文,所以需要先把焦点移入子窗体,再移到其中一个可聚焦控件。记录显示的红色边框也与当前焦点上下文有关。焦点移出数据表后,选中显示可能消失,即使 Bookmark 仍指向目标记录。

备注:内容仅供参考。