Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在VBA中,如何比较用户定义类型(UDT)的两个实例?I';我得到一个类型不匹配_Vba_User Defined Types_Type Mismatch - Fatal编程技术网

在VBA中,如何比较用户定义类型(UDT)的两个实例?I';我得到一个类型不匹配

在VBA中,如何比较用户定义类型(UDT)的两个实例?I';我得到一个类型不匹配,vba,user-defined-types,type-mismatch,Vba,User Defined Types,Type Mismatch,我有一个定义UDT的模块,如下所示: Private Type UserData uName As String 'user name uDate As Date 'date/time of last interaction End Type Sub TestCheck() Dim testRec(1) As UserData testRec(0).uName = "a" testRec(0).uD

我有一个定义UDT的模块,如下所示:

Private Type UserData
    uName As String         'user name
    uDate As Date           'date/time of last interaction
End Type
Sub TestCheck()
    Dim testRec(1) As UserData
    testRec(0).uName = "a"
    testRec(0).uDate = Date
    testRec(1) = testRec(0)
    
    If testRec(1) = testRec(0) Then
        Debug.Print "Records match"
    Else
        Debug.Print "Records don't match"
    End If
End Sub
Sub TestCheck()
    Dim testRec(1) As UserData
    testRec(0).uName = "a"
    testRec(0).uDate = Date

    testRec(1) = testRec(0)

    If UserDataEqual(testRec(1), testRec(0)) Then
        Debug.Print "Records match"
    Else
        Debug.Print "Records don't match"
    End If
End Sub
我尝试使用一个简单的测试函数来比较UDT的两个不同实例,如下所示:

Private Type UserData
    uName As String         'user name
    uDate As Date           'date/time of last interaction
End Type
Sub TestCheck()
    Dim testRec(1) As UserData
    testRec(0).uName = "a"
    testRec(0).uDate = Date
    testRec(1) = testRec(0)
    
    If testRec(1) = testRec(0) Then
        Debug.Print "Records match"
    Else
        Debug.Print "Records don't match"
    End If
End Sub
Sub TestCheck()
    Dim testRec(1) As UserData
    testRec(0).uName = "a"
    testRec(0).uDate = Date

    testRec(1) = testRec(0)

    If UserDataEqual(testRec(1), testRec(0)) Then
        Debug.Print "Records match"
    Else
        Debug.Print "Records don't match"
    End If
End Sub
我得到编译错误:testRec(1)=testRec(0)上的类型不匹配


我真的不想为了检查等价性而遍历每个实例的每个成员。UDT不应该充当变量吗?如果我必须循环每个实例的每个成员来比较它们,那么使用UDT确实不会为我节省任何东西。有没有一种方法可以在不经过成员循环的情况下进行比较?

根据Brian M Stafford的评论,对于任何有相同问题的人,简单的答案是否定的。
然而,这里有一个简单的函数来完成这项工作:

Private Function UserDataEqual(ByRef varA As UserData, ByRef varB As UserData) As Boolean
    If varA.uName = varB.uName _
    And varA.uDate = varB.uDate Then
        UserDataEqual = True
    Else
        UserDataEqual = False
    End If
End Function
其用途如下:

Private Type UserData
    uName As String         'user name
    uDate As Date           'date/time of last interaction
End Type
Sub TestCheck()
    Dim testRec(1) As UserData
    testRec(0).uName = "a"
    testRec(0).uDate = Date
    testRec(1) = testRec(0)
    
    If testRec(1) = testRec(0) Then
        Debug.Print "Records match"
    Else
        Debug.Print "Records don't match"
    End If
End Sub
Sub TestCheck()
    Dim testRec(1) As UserData
    testRec(0).uName = "a"
    testRec(0).uDate = Date

    testRec(1) = testRec(0)

    If UserDataEqual(testRec(1), testRec(0)) Then
        Debug.Print "Records match"
    Else
        Debug.Print "Records don't match"
    End If
End Sub

谢谢你回答我的问题,布莱恩。

这类活动是上课的目的。使用适当的方法创建类,而不是用户定义的类型。在这里,我们定义了一个名为UserData的类,它具有一个预先声明的Id,以便我们可以将该类用作UserData工厂。在这个例子中,我们有

用户数据类

' User Rubberduck annotations to set the predecalredId to True
'@PredeclaredId
Option Explicit

Public Enum UserDataType

    udDate
    udName

End Enum

Private Type Properties
    UserData As Object
End Type

Private p As Properties


Public Function Make(ByVal ipName As String, ByVal ipDateAndTime As Date) As UserData
    
    With New UserData
    
        Set Make = .Self(ipName, ipDateAndTime)
    
    End With
    
End Function

Public Function Self(ByVal ipName As String, ByVal ipDateAndTime As Date) As UserData

    ' Use late bound crreation of a scripting dictionary to avoid reference issues
    Set p.UserData = CreateObject("Scripting.Dictionary")
    
    With p.UserData
    
        .Add udName, ipName
        .Add udDate, ipDateAndTime
    
    End With
    
    Set Self = Me
    
End Function



Public Property Get Item(ByVal ipEnum As Long) As Variant
    Item = p.UserData.Item(ipEnum)
End Property

Public Property Let Item(ByVal ipEnum As Long, ByVal ipValue As Variant)

    p.UserData.Item(ipEnum) = ipValue
End Property

Public Function SameAs(ByVal ipUserData As UserData) As Boolean

    SameAs = False
    
    Dim myIndex As Long
    For myIndex = 0 To p.UserData.Count - 1
    
        If Me.Item(myIndex) <> ipUserData.Item(myIndex) Then Exit Function
        
    Next
    
    SameAs = True

End Function

如你所见。你可以看到。要更改不同成员集的UserData类,只需更改枚举(前提是保留简单变量)。

您需要逐个成员进行比较。您可以创建一个方法来简化此任务。@BrianMStafford谢谢。天哪,这正是我害怕的。不幸的是,上面的例子是对我的实际UDT的简化,我需要为每个单独的UDT成员使用函数,除非有办法将UDT视为类型变量的数组。你说的是多少UDT成员?它是嵌套的,所以有一个包含4个成员的“顶级”UDT。其中2名成员是其他UDT。其中一个是上面列出的一个(有2名成员),另一个有3名成员。因此,总共需要进行7次比较。该方法特定于UDT。这意味着每个UDT都会有自己的方法。是的,我一开始就在讨论如何使用类路径,但我避免了它,因为我希望类型对它们的模块是私有的,并且不打算让它们变得太复杂。那是在我意识到你不能测试他们是否平等之前。不管怎样,看起来您也必须在类中为它编写函数。谢谢你的意见。简化对象创建的类的极好示例。