我看过许多帖子试图描述这个bug,但他们没有正确地框架这个问题来重现……或者不是以我使用通用技术遇到的bug的方式设置场景。
当窗体的记录集设置为虚拟记录集,然后由DAO recordsetclone语句引用时,就会发生错误。此时将显示“选择数据源”对话框,而不是将记录集设置为表单的记录集(通过克隆)。
我们最常用的用法是将checkbox控件添加到详细信息表单中,以便用户选择一条或多条记录进行进一步处理。我在许多应用程序中多次使用过这种技术,但现在它失败了。
注意:我已经确认此代码在Access 2010中工作正常。
我正在使用带有32位Office安装的Windows 10专业版
要设置并重现错误,请执行以下操作:
创建一个新的ACCDB数据库,将以下引用添加到默认引用中: Microsoft ActiveX Data Objects 6.1 Library Microsoft ADO Ext.2.8用于DDL和安全性
创建测试表: TestId、AutoNumber、PK TestText、短文本
将大约10行追加到表中。
创建包含3个控件的未绑定窗体: Checkbox、Name: Selected、控件源: Selected Textbox、Name: TestId、Control Source: TestId Textbox、Name: TestText、Control Source: TextText
在窗体的页眉中添加命令按钮: Name: cmdTest,Caption: Test Set the form Default View: Continuous
在Form_Open中,调用一个子SetRecordsource,它创建一个记录集,并添加一个"Selected“列供用户检查他们想要的记录。
命令按钮cmdTest将尝试引用窗体的记录源。正是在尝试引用窗体的记录源时,出现了错误。不是进行引用,而是弹出“选择数据源”对话框。
完整窗体的VBA代码:
Option Compare Database
Option Explicit
Private Sub cmdTest_Click()
On Error GoTo errHandler
Dim rs As DAO.Recordset
Set rs = Me.RecordsetClone
' Using an ADODB recordset works but is an ugly solution
' To test comment out the Dim DAO and Set rs statements above and uncomment the next 2 lines.
' Dim rs As ADODB.Recordset
' Set rs = Me.Recordset
rs.MoveFirst
With rs
Do While Not .EOF
Debug.Print .Fields("Selected"), .Fields("TestId"), .Fields("TestText")
.MoveNext
Loop
End With
Set rs = Nothing
ExitSub:
Exit Sub
errHandler:
MsgBox "Error in " & Me.Name & ".SetRecordsource " & Err.Number & " - " & Err.Description
Resume ExitSub
End Sub
Private Sub SetRecordsource()
Dim rs As ADODB.Recordset 'the virtual recordset to hold the source data plus the boolean Selected field
Dim rsSource As DAO.Recordset 'dim the source recordset
Set rs = New ADODB.Recordset
With rs
.Fields.Append "Selected", adboolean
.Fields.Append "TestId", adInteger, , adFldKeyColumn
.Fields.Append "TestText", adVarChar, 80
.CursorLocation = adUseClient
.LockType = adLockOptimistic
.CursorType = adOpenKeyset
.Open
Set rsSource = CurrentDb.OpenRecordset("Select TestId, TestText from Test", dbOpenDynaset)
rsSource.MoveFirst
Do Until rsSource.EOF
.AddNew
.Fields("Selected") = 0 'set the checkboxes to unchecked
.Fields("TestId") = rsSource.Fields(0)
.Fields("TestText") = rsSource.Fields(1)
.Update
rsSource.MoveNext
Loop
End With
Set Me.Recordset = rs 'Set the form's recordset = to our virtual recordset
Set rsSource = Nothing
Set rs = Nothing
ExitSub:
Exit Sub
err_handler:
MsgBox "Error in " & Me.Name & ".SetRecordsource " & Err.Number & " - " & Err.Description
Resume ExitSub
End Sub 'SetRecordsource
打开窗体并单击Test命令按钮以重现错误。
建议的一种解决方案是使用ADODB记录集并将其设置为Me.Recordset而不是Me.Recordsetclone。虽然这确实有效,但它是一个丑陋的解决方案,因为您现在正在对窗体的记录源进行操作,并且当循环遍历记录以查找Selected = True在窗体上移动当前记录的行时。不仅当前记录指针会移动,而且如果有超过可显示的行数,用户会看到表单的记录滚动。
任何帮助、确认或建议都将不胜感激。
提前感谢!
发布于 2019-03-11 19:40:17
在另一个论坛上,这个问题的解决方案是使用一个ADODB记录集,然后通过Recordset.Clone将表单克隆到该记录集。在上面的代码中,它引用了一个“丑陋”的解决方案:
“使用ADODB记录集工作,但这是一个丑陋的解决方案”来测试,注释掉Dim DAO,设置上面的rs语句,并取消注释接下来的2行。
‘Dim rs As ADODB.Recordset
‘设置rs = Me.Recordset
设置rs = Me.Recordset将在表单上操作(不需要)。
但是使用ADODB记录集然后设置rs = Me.Recordset.Clone是有效的,不会对表单进行操作,也不会弹出数据源对话框。
2016年有些事情发生了变化,但这确实有效,可能会对其他人有所帮助。您可能还想阅读:Create In-Memory ADO Recordsets at Database Journal
https://stackoverflow.com/questions/55087030
复制相似问题