通过父窗体按钮访问记录时出现Run-time error 2105
问题分析与解决方案
问题根源
父窗体按钮点击后,当前活动数据对象是父窗体,而你调用DoCmd.GoToRecord时用了acActiveDataObject,相当于在父窗体的记录集里查找子窗体的记录号,必然找不到对应记录,触发2105错误(无法转到指定记录)。而双击子窗体字段时,子窗体是活动对象,acActiveDataObject正确指向子窗体记录集,所以逻辑正常。
修复方案
核心是明确指定操作的对象为子窗体,不要依赖acActiveDataObject,同时优化冗余的Requery操作,避免不必要的性能损耗。
修改后的代码如下:
Public Sub AddRemoveFromReport() On Error GoTo ErrCheck Dim dblLineNo As Double ' 改为局部变量,避免全局变量冲突 Dim frm As Form Set frm = Me ' 明确引用当前子窗体对象 dblLineNo = Nz(frm.CurrentRecord, 1) ' 切换OnReport状态 frm.OnReport = Not frm.OnReport ' 重新查询子窗体及关联的其他子窗体 frm.Requery frm.Parent.frmPRJTrackerReportDetailTempOnReport.Form.Requery frm.Parent.frmPRJTrackerReportDetailTempAvailable.Form.Requery Application.Echo False ' 明确指定操作对象为当前子窗体,而非依赖活动对象 DoCmd.GoToRecord acDataForm, frm.Name, acLast ' 尝试定位到原记录号 DoCmd.GoToRecord acDataForm, frm.Name, acGoTo, dblLineNo Application.Echo True Exit Sub ErrCheck: Select Case Err.Number Case 2427 MsgBox "Please select an item from the list before continuing.", vbOKOnly + vbInformation Case 2105 ' 原记录号不存在,尝试定位到上一条 If dblLineNo > 1 Then DoCmd.GoToRecord acDataForm, frm.Name, acGoTo, dblLineNo - 1 Else ' 如果是第一条记录,定位到第一条可用记录 DoCmd.GoToRecord acDataForm, frm.Name, acFirst End If Application.Echo True Resume Next Case Else MsgBox "Error " & Err.Number & ": " & Err.Description End Select Application.Echo True End Sub
关键改动说明
- 明确指定操作对象:用
acDataForm+frm.Name替代acActiveDataObject,确保始终操作子窗体的记录集,不受当前焦点影响; - 改用局部变量:将
dblLineNo声明为子过程的局部变量,避免全局变量可能带来的意外覆盖问题; - 简化状态切换:用
frm.OnReport = Not frm.OnReport替代原有的If-Else逻辑,更简洁; - 严谨处理越界情况:在2105错误分支里增加对
dblLineNo=1的判断,避免出现负数记录号的错误; - 优化错误提示:在默认错误分支里增加错误编号,方便排查。
父窗体按钮调用方式
确保父窗体按钮的点击事件里,正确引用子窗体的过程,比如:
Private Sub btnToggleReport_Click() ' 假设子窗体控件名为frmChild(根据你的实际控件名修改) Me.frmChild.Form.AddRemoveFromReport End Sub
内容的提问来源于stack exchange,提问作者BBPerth
相关产品推荐
相关产品推荐

