比较两个记录集变量会导致类型不匹配

时间:2013-11-23 12:07:18

标签: ms-access access-vba recordset

我有一个包含多个子表单的绑定表单。其中一些子表单可以有0个或多个记录,其他子表单有1个或更多 表格始终以只读方式打开,其上有“编辑”和“关闭”按钮 当用户点击编辑按钮时,我将当前记录的内容保存到子表单的所有记录中,以便当他/她点击关闭按钮时我可以询问是否保存,如果没有,则丢弃更改从保存的记录中恢复。

到目前为止,这是编辑按钮的代码(其中GclnAllCnts是Dictionary类型的全局变量):

Private Sub EditLibroBtn_Click()
    On Error GoTo Err_EditLibroBtn_Click
    Dim lngID         As Long
    Dim ctlCnt        As Control
    Dim rs            As Recordset
    lngID = Me.ID
    Set GclnAllCnts = New Dictionary
    GclnAllCnts.Add Me.Name, Me.RecordsetClone
    For Each ctlCnt In Me.Controls
        If (ctlCnt.ControlType = acSubform) Then
            Set rs = ctlCnt.Form.RecordsetClone
            If rs.RecordCount > 0 Then
                GclnAllCnts.Add ctlCnt.Name, ctlCnt.Form.RecordsetClone
            Else
                GclnAllCnts.Add ctlCnt.Name, Null
            End If
        End If
    Next
    DoCmd.Close acForm, Me.Name
    DoCmd.OpenForm GCstMainFrmName, , , "ID = " & lngID, acFormEdit, acDialog

Exit_EditLibroBtn_Click:
    Set ctlCnt = Nothing
    Set rs = Nothing
    Exit Sub

Err_EditLibroBtn_Click:
    MsgBox err.Description & vbNewLine & "Error number: " & err.Number, vbCritical, "Errore"
    Resume Exit_EditLibroBtn_Click
End Sub

这是关闭按钮的代码:

Private Sub ChiudiBtn_Click()
    On Error GoTo Err_ChiudiBtn_Click
    Dim intBoxAwr   As Integer
    Dim stSQL       As String
    Dim vKey        As Variant
    Dim ctlCnt      As Control
    Dim clnAllCnts  As Dictionary
    Dim bSaveNeeded As Boolean
    bSaveNeeded = False
    If (Me.AllowEdits And Me.ID <> "" And Not IsNull(Me.ID)) Then
        Set clnAllCnts = New Dictionary
        clnAllCnts.Add Me.Name, Me.RecordsetClone
        For Each ctlCnt In Me.Controls
            If (ctlCnt.ControlType = acSubform) Then
                Set rs = ctlCnt.Form.RecordsetClone
                If rs.RecordCount > 0 Then
                    clnAllCnts.Add ctlCnt.Name, ctlCnt.Form.RecordsetClone
                Else
                    clnAllCnts.Add ctlCnt.Name, Null
                End If
            End If
        Next
       If clnAllCnts.Count <> GclnAllCnts.Count Then
            bSaveNeeded = True
        Else
            For Each vKey In clnAllCnts.keys()
                If Not GclnAllCnts.Exists(vKey) Then
                    bSaveNeeded = True
                    Exit For
                Else
'*********** Next Gives error **********
                    If clnAllCnts.Item(vKey) <> GclnAllCnts.Item(vKey) Then
                        bSaveNeeded = True
                        Exit For
                    End If
                End If
            Next
        End If
        If bSaveNeeded Then
            intBoxAwr = MsgBox("Salvare le modifiche al libro?", vbYesNo + vbQuestion, "Salvare")
            If intBoxAwr = vbYes Then
        'etc., omitting code
End Sub

我得到的错误是类型不匹配(编号13),它由<>比较给出(我可以调试。IsNull(clnAllCnts.Item(vKey))和{{1} }。

如何比较两个记录集变量?

1 个答案:

答案 0 :(得分:0)

通过简单地说If rst1 <> rst2来比较两个Recordset对象无论如何都可能有点冒险,因为这究竟意味着什么?如果Truerst1确实 不同的对象(即使它们属于同一对象类型),这样的表达式每次都可以返回rst2

您似乎对两个Recordset的内容是否相同感兴趣。在这种情况下,我倾向于序列化记录集数据并存储结果String,而不是存储Recordset对象本身。

在这种情况下,以下VBA功能可能会有所帮助。它遍历记录集对象并生成包含当前记录集数据的类似JSON的字符串。

(注意,该函数可能不一定产生有效的JSON。它不会转义非打印字符,如vbCrvbLf。它不会转义反斜杠(\)它将所有值存储为“字符串”或null。换句话说,在其当前形式中,它不是为了生成一个以后可以反序列化的字符串而设计的。)

Private Function rstSerialize(ByVal rst As DAO.Recordset)
    ' loop through the recordset and generate a JSON-like string
    '     NB: This code will NOT necessarily produce valid JSON!
    '
    Dim s As String, fld As DAO.Field, rowCount As Long, fldCount As Long

    s = "{"
    If Not (rst.BOF And rst.EOF) Then
        rst.MoveFirst
        rowCount = 0
        Do Until rst.EOF
            If rowCount > 0 Then
                s = s & ", "
            End If
            s = s & """row"": {"
            fldCount = 0
            For Each fld In rst.Fields
                If fldCount > 0 Then
                    s = s & ", "
                End If
                s = s & """" & fld.Name & """: " & IIf(IsNull(fld.Value), "null", """" & fld.Value & """")
                fldCount = fldCount + 1
            Next
            s = s & "}"
            rowCount = rowCount + 1
            rst.MoveNext
        Loop
    End If
    s = s & "}"
    rstSerialize = s
End Function

数据示例:如果Recordset包含

DonorID  Amount
-------  ------
      1      10
      2      20

该函数将返回字符串

{"row": {"DonorID": "1", "Amount": "10"}, "row": {"DonorID": "2", "Amount": "20"}}

用法示例:在包含子表单的表单上,主表单上的按钮可以执行以下操作

Private Sub Command3_Click()
    Dim rst As DAO.Recordset, originalState As String
    Set rst = Me.MemberDonationsSubform.Form.RecordsetClone
    originalState = rstSerialize(rst)
    rst.MoveFirst
    rst.Edit
    rst!Amount = rst!Amount + 1
    rst.Update
    Debug.Print "(Recordset updated.)"
    If rstSerialize(rst) = originalState Then
        Debug.Print "Recordset does not appear to have changed."
    Else
        Debug.Print "Recordset appears to have changed."
    End If
End Sub

将在VBA立即窗口中打印以下内容

(Recordset updated.)
Recordset appears to have changed.