VBA比较变体

VBA比较变体,vba,excel,Vba,Excel,我要做的是遍历变量,看看里面的所有内容是否匹配 …但是有没有一种更快更有效的方法来比较变体?我真的不需要知道里面是什么 如果我在比较字符串,如果string1=string2,那么。。。就够了。在这种情况下,如果Var1=Var2,那么 Var1 = Sheets(1).Range("A1:B10") Var2 = Sheets(1).Range("C1:D10") A B C D ABC DEF ABC DEF SBC

我要做的是遍历变量,看看里面的所有内容是否匹配

…但是有没有一种更快更有效的方法来比较变体?我真的不需要知道里面是什么

如果我在比较字符串,如果string1=string2,那么。。。就够了。在这种情况下,如果Var1=Var2,那么

Var1 = Sheets(1).Range("A1:B10")
Var2 = Sheets(1).Range("C1:D10")


    A      B      C     D
   ABC    DEF    ABC   DEF  
   SBC    SEF    SBC   SEF  
   FBC    FEF    FBC   FEF  
   RBC    REF    RBC   REF  

数据将主要是文本,并且在范围内的指定行数中,大多数情况下,列A和B应等于列C和D。我需要知道的是,指定行中的A列和B列的内容是否与D列和C列的内容相同。

如果您试图比较您在评论中提到的两个范围,我建议使用A for each循环迭代第一个范围rng1,并使用MATCH查看rng1中的每个项目是否在rng2中,这将比显式比较每对更快。

如果您试图比较您在评论中提到的两个范围,我建议使用for-each循环在第一个范围rng1上迭代,并使用MATCH查看rng1中的每个项目是否都在rng2中,这将比显式比较每一对更快。

您看到的是两个@2维数组

这个简短的例程向VBE的即时窗口Ctrl+G输出尺寸和值

Sub str_test()
    Dim v As Long, w As Long, vABs As Variant, vCDs As Variant

    With ActiveSheet
        vABs = .Range("A1:B10").Value2
        vCDs = .Range("C1:D10").Value2
        Debug.Print LBound(vABs, 1) & ":" & UBound(vABs, 1)
        Debug.Print LBound(vABs, 2) & ":" & UBound(vABs, 2)
        Debug.Print LBound(vCDs, 1) & ":" & UBound(vCDs, 1)
        Debug.Print LBound(vCDs, 2) & ":" & UBound(vCDs, 2)

        For v = LBound(vABs, 1) To UBound(vABs, 1)
            For w = LBound(vABs, 2) To UBound(vABs, 2)
                Debug.Print vABs(v, w) & " - " & vCDs(v, w)
            Next w
        Next v
    End With
End Sub
结果:

str_test
1:10
1:2
1:10
1:2
LOGG - JWSA
EGXL - SBQI
WKSL - ZITO
VUKB - MCWY
(etc, etc, blah, blah...)

您应该能够从那里进行字符串比较。

您看到的是两个@2维数组

这个简短的例程向VBE的即时窗口Ctrl+G输出尺寸和值

Sub str_test()
    Dim v As Long, w As Long, vABs As Variant, vCDs As Variant

    With ActiveSheet
        vABs = .Range("A1:B10").Value2
        vCDs = .Range("C1:D10").Value2
        Debug.Print LBound(vABs, 1) & ":" & UBound(vABs, 1)
        Debug.Print LBound(vABs, 2) & ":" & UBound(vABs, 2)
        Debug.Print LBound(vCDs, 1) & ":" & UBound(vCDs, 1)
        Debug.Print LBound(vCDs, 2) & ":" & UBound(vCDs, 2)

        For v = LBound(vABs, 1) To UBound(vABs, 1)
            For w = LBound(vABs, 2) To UBound(vABs, 2)
                Debug.Print vABs(v, w) & " - " & vCDs(v, w)
            Next w
        Next v
    End With
End Sub
结果:

str_test
1:10
1:2
1:10
1:2
LOGG - JWSA
EGXL - SBQI
WKSL - ZITO
VUKB - MCWY
(etc, etc, blah, blah...)

您应该能够从那里进行字符串比较。

如果您试图比较两个形状相同的范围,并且它们的值是数字,您可以在VBA中使用工作表函数SumX2MY2A,B。该函数计算相应条目之间的差值平方。当且仅当结果为0时,这些数字是相同的。这可能不是最有效的方法-但对于大型阵列,它可能会凭借使用Excel的计算引擎而不是解释的VBA代码而胜出。你可以这样使用它:

Sub test()
    Dim A As Variant, B As Variant
    A = Range("A1:B2").Value
    B = Range("C1:D2").Value
    If Application.WorksheetFunction.SumX2MY2(A, B) = 0 Then
        Debug.Print "Values the same"
    Else
        Debug.Print "Values different"
    End If   
End Sub
Function SameVals(R1 As Range, R2 As Range) As Boolean
    Range("X1").FormulaArray = "= Sum(If(" & _
                               R1.Address(ReferenceStyle:=xlR1C1) & _
                               "=" & R2.Address(ReferenceStyle:=xlR1C1) & _
                               ",0,1))"
    SameVals = Range("X1").Value = 0
    Range("X1").ClearContents
End Function
运行两次,当两个范围包含相同的值时运行一次,当某些值不同时运行一次

编辑时:如果要比较包含相等文本的两个范围,并且不希望使用嵌套循环,则可以使用数组公式。选择一个单元格,例如X1,为了安全起见,您不打算使用它来隐藏它,并创建如下函数:

Sub test()
    Dim A As Variant, B As Variant
    A = Range("A1:B2").Value
    B = Range("C1:D2").Value
    If Application.WorksheetFunction.SumX2MY2(A, B) = 0 Then
        Debug.Print "Values the same"
    Else
        Debug.Print "Values different"
    End If   
End Sub
Function SameVals(R1 As Range, R2 As Range) As Boolean
    Range("X1").FormulaArray = "= Sum(If(" & _
                               R1.Address(ReferenceStyle:=xlR1C1) & _
                               "=" & R2.Address(ReferenceStyle:=xlR1C1) & _
                               ",0,1))"
    SameVals = Range("X1").Value = 0
    Range("X1").ClearContents
End Function
这样测试它:

Sub test()
    MsgBox SameVals(Range("A1:B4"), Range("C1:D4"))
End Sub
在测试用例中,数组公式

{= SUM(IF($A$1:$B$4=$C$1:$D$4,0,1)}
在X1中组装。它首先创建一个由0和1组成的数组,表示范围不同的位置,然后对结果求和


与检查范围是否相等的明显嵌套for循环方法相比,这有缺点,但是,如果您正在测试大范围的相等性和直接迭代方法的性能,那么您可以尝试使用此方法。

如果您试图比较两个形状相同的范围,并且它们的值是数字,则可以在VBA中使用工作表函数SumX2MY2A,B.该函数计算相应条目之间差异的平方。当且仅当结果为0时,这些数字是相同的。这可能不是最有效的方法-但对于大型阵列,它可能会凭借使用Excel的计算引擎而不是解释的VBA代码而胜出。你可以这样使用它:

Sub test()
    Dim A As Variant, B As Variant
    A = Range("A1:B2").Value
    B = Range("C1:D2").Value
    If Application.WorksheetFunction.SumX2MY2(A, B) = 0 Then
        Debug.Print "Values the same"
    Else
        Debug.Print "Values different"
    End If   
End Sub
Function SameVals(R1 As Range, R2 As Range) As Boolean
    Range("X1").FormulaArray = "= Sum(If(" & _
                               R1.Address(ReferenceStyle:=xlR1C1) & _
                               "=" & R2.Address(ReferenceStyle:=xlR1C1) & _
                               ",0,1))"
    SameVals = Range("X1").Value = 0
    Range("X1").ClearContents
End Function
运行两次,当两个范围包含相同的值时运行一次,当某些值不同时运行一次

编辑时:如果要比较包含相等文本的两个范围,并且不希望使用嵌套循环,则可以使用数组公式。选择一个单元格,例如X1,为了安全起见,您不打算使用它来隐藏它,并创建如下函数:

Sub test()
    Dim A As Variant, B As Variant
    A = Range("A1:B2").Value
    B = Range("C1:D2").Value
    If Application.WorksheetFunction.SumX2MY2(A, B) = 0 Then
        Debug.Print "Values the same"
    Else
        Debug.Print "Values different"
    End If   
End Sub
Function SameVals(R1 As Range, R2 As Range) As Boolean
    Range("X1").FormulaArray = "= Sum(If(" & _
                               R1.Address(ReferenceStyle:=xlR1C1) & _
                               "=" & R2.Address(ReferenceStyle:=xlR1C1) & _
                               ",0,1))"
    SameVals = Range("X1").Value = 0
    Range("X1").ClearContents
End Function
这样测试它:

Sub test()
    MsgBox SameVals(Range("A1:B4"), Range("C1:D4"))
End Sub
在测试用例中,数组公式

{= SUM(IF($A$1:$B$4=$C$1:$D$4,0,1)}
在X1中组装。它首先创建一个由0和1组成的数组,表示范围不同的位置,然后对结果求和


与检查范围是否相等的明显嵌套for循环方法相比,这有缺点,但如果您正在测试大范围是否相等,那么直接迭代方法的性能似乎是一个问题,您可以尝试使用此方法。

以下是不带VBA的公式方法:

快速突出显示公式差异的另一种方法:

 A       B       C       D       E           F
ABC     DEF     ABC      x      TRUE        FALSE
SBC     SEF     SBC     SEF     TRUE        TRUE
FBC     FEF     FBC     FEF     TRUE        TRUE
RBC     REF     RBC     REF     TRUE        TRUE

ABC     DEF     ABC     DEF     =A7=C7      =B7=D7
SBC     SEF     SBC     SEF     =A8=C8      =B8=D8
FBC     FEF     FBC     FEF     =A9=C9      =B9=D9
RBC     REF     RBC     REF     =A10=C10    =B10=D10
这是VBA中的匹配函数:

Option Explicit

Public Sub compareValues()
    Dim rng1 As Range, rng2 As Variant, rng3 As Variant
    Dim ws As Worksheet, result As Variant, cel As Range

    Set ws = Sheet1
    Set rng1 = ws.Range("A1:B10")
    rng2 = Application.Transpose(ws.Range("C1:C10"))
    rng3 = Application.Transpose(ws.Range("D1:D10"))

    For Each cel In rng1
        cel = Trim(cel)
        If Len(cel) > 0 Then
            result = Application.Match(cel, rng2, 0)
            If IsError(result) Then
                result = Application.Match(cel, rng3, 0)
                If IsError(result) Then cel.Interior.Color = vbYellow
            End If
        End If
    Next
End Sub

以下是不带VBA的公式方法:

快速突出显示公式差异的另一种方法:

 A       B       C       D       E           F
ABC     DEF     ABC      x      TRUE        FALSE
SBC     SEF     SBC     SEF     TRUE        TRUE
FBC     FEF     FBC     FEF     TRUE        TRUE
RBC     REF     RBC     REF     TRUE        TRUE

ABC     DEF     ABC     DEF     =A7=C7      =B7=D7
SBC     SEF     SBC     SEF     =A8=C8      =B8=D8
FBC     FEF     FBC     FEF     =A9=C9      =B9=D9
RBC     REF     RBC     REF     =A10=C10    =B10=D10
这是VBA中的匹配函数:

Option Explicit

Public Sub compareValues()
    Dim rng1 As Range, rng2 As Variant, rng3 As Variant
    Dim ws As Worksheet, result As Variant, cel As Range

    Set ws = Sheet1
    Set rng1 = ws.Range("A1:B10")
    rng2 = Application.Transpose(ws.Range("C1:C10"))
    rng3 = Application.Transpose(ws.Range("D1:D10"))

    For Each cel In rng1
        cel = Trim(cel)
        If Len(cel) > 0 Then
            result = Application.Match(cel, rng2, 0)
            If IsError(result) Then
                result = Application.Match(cel, rng3, 0)
                If IsError(result) Then cel.Interior.Color = vbYellow
            End If
        End If
    Next
End Sub

我首先想到的直截了当的解决办法。运行时间约为0.12毫秒:

oRange1 = Range("A1:B10")
oRange2 = Range("C1:D10")

For i = 1 To 10
    For j = 1 To 2
        If oRange1(i, j) <> oRange2(i, j) Then MsgBox "Not equal.": Exit For
    Next j
Next i

我首先想到的直截了当的解决办法。运行时间约为0.12毫秒:

oRange1 = Range("A1:B10")
oRange2 = Range("C1:D10")

For i = 1 To 10
    For j = 1 To 2
        If oRange1(i, j) <> oRange2(i, j) Then MsgBox "Not equal.": Exit For
    Next j
Next i

你能提供你的代码吗?我还没有编码。现在我只有两个变量的值为f

rom 2范围[Var1=Sheets1.RangeA1:B10:Var2=Sheets1.RangeC1:D10]您应该指定正在进行的比较类型,以及这些范围中可能存在的输入类型。你在寻找他们之间的身份吗?i、 e.var1与var2具有相同的值,并且它们的顺序相同,是否查找两者具有相同的值,但顺序不同?它可以改变你推断答案的速度,因此你似乎需要有完全相同的值,即A1需要等于C1等。这样你就无法避免显式比较,你必须按照Jeeped的建议迭代整个过程,否则你可能会得到假阳性,虽然我会在比较中出现错误的情况下添加一个中断,但是这样一来,一旦你知道它不好,你就不需要继续检查了。是的,我所需要的只是知道A1:B10范围内的文本是否与C1:D10范围内的文本相同。你能提供你的代码吗?我还没有编码它。现在,我有两个变量,它们的值来自两个范围[Var1=Sheets1.RangeA1:B10:Var2=Sheets1.RangeC1:D10],您应该指定正在进行的比较类型,以及这些范围中可能存在的输入类型。你在寻找他们之间的身份吗?i、 e.var1与var2具有相同的值,并且它们的顺序相同,是否查找两者具有相同的值,但顺序不同?它可以改变你推断答案的速度,因此你似乎需要有完全相同的值,即A1需要等于C1等。这样你就无法避免显式比较,你必须按照Jeeped的建议迭代整个过程,否则你可能会得到假阳性,虽然我会在比较中出现错误的情况下添加一个中断,但是这样一来,一旦你知道它不好,你就不需要继续检查了。是的,我所需要的只是知道A1:B10范围内的文本是否与C1:D10范围内的文本相同。有趣的是。这比我希望的要复杂得多,甚至比迭代更复杂,但它看起来确实很整洁!我将尝试更好地理解它实际上在做什么,或者更确切地说,它是如何做的。非常感谢。有趣的这比我希望的要复杂得多,甚至比迭代更复杂,但它看起来确实很整洁!我将尝试更好地理解它实际上在做什么,或者更确切地说,它是如何做的。非常感谢。事实上,这会更快。我没有考虑过使用公式,但它们可能是最好的。match也适用于VBA,而不仅仅适用于excel中的forumlas,因此如果它是更大宏的一部分,这不是问题x=worksheetfunction.Matcharg1、arg2、Arg3确实会更快。我没有想过使用公式,但它们可能是最好的。match也适用于VBA,而不仅仅适用于excel中的forumlas,因此如果它是更大宏的一部分,这不是问题x=worksheetfunction.Matcharg1、arg2、Arg3该范围将主要包含文本。。。但我认为变体上的某些匹配函数可能会起到作用。@jony我添加了第二种方法,该方法适用于文本,尽管我怀疑它是否真的比直接的迭代方法好。范围将主要包含文本。。。但我认为变量上的某些匹配函数可能会起到作用。@jony我添加了第二种方法,该方法适用于文本,尽管我怀疑它是否真的比直接的迭代方法好。我对公式的经验比VBA的经验要少,但是如果Range1包含与Range2相同的精确文本,是否有一个公式可以返回单个真/假值?这将迅速而容易地解决它。就像一个匹配中的一个匹配?我对公式比VBA更缺乏经验,但是如果Range1包含与Range2相同的精确文本,是否有一个公式可以返回单个真/假值?这将迅速而容易地解决它。像火柴里面的火柴?