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 仍指向目标记录。
备注:内容仅供参考。
