比较excel中的两个工作表值

时间:2017-08-24 01:40:21

标签: excel vba excel-vba

如何将一个列的工作表1的所有值与另一个具有不同工作表2的列值进行比较,如果匹配则将与工作表1的一列相对应的值返回到另一列工作表-2在excel?

3 个答案:

答案 0 :(得分:0)

假设您的值位于名为Sheet1Sheet2的工作表的A列中。然后,您可以将以下公式放入B1的{​​{1}}中并向下拖动以覆盖您所需的范围:Sheet2

或者,如果您更喜欢使用VBA,请将此代码放入模块中:

=IF(Sheet1!A1=Sheet2!A1,Sheet2!A1,"")

答案 1 :(得分:0)

如果我理解正确,这就是你想要的,

<强> Sheet 1中

enter image description here

<强> Sheet 2中

enter image description here

B2的{​​{1}}中输入以下公式,然后向下拖动图片,

sheet2

答案 2 :(得分:0)

我只能回答部分问题:比较两列并检测到它们不同

Tony M上面的答案中,你有一个很好的教程答案。

但是,这对大型数据集执行速度非常慢,因为:

  1. 一次读取一个单元格的范围非常慢;
  2. 逐个比较值是低效的,特别是对于字符串,当值的数量达到数万时,
  3. 点(1)是重要的一点:VBA使用var = Range("A1")获取单个单元所花费的时间相同,因为它使用var = Range("A1:Z1024")一次性获取整个范围;并且与工作表的每次交互所花费的时间是VBA中字符串比较的四倍,并且比浮点小数之间的比较长二十倍;反过来,它比整数比较长三倍。

    因此,如果您一次性读取整个范围,并且在VBA中处理Range.Value2数组,那么您的代码可能快四倍,可能快一百倍。

    这是Office 2010和2013(我对它们进行了测试);对于旧版本的Excel,您将看到引用时间介于1/50 th 和1/500 th 之间,对于每个VBA与单元格或范围的交互细胞。因为在旧版本和新版本的Excel中,VBA操作仍然是一位数的微秒数,所以这样会慢一点:你的代码运行速度至少要快一百倍,可能要运行数千次更快,如果你避免在旧版本的Excel中从工作表中逐个单元格读取。

    如此大的收益 - 用户可感知的间隔 - 在单个“点击”中获取范围,然后在VBA中对阵列的每个项目执行比较。

    
    arr1  = Range1.Values
    arr2  = Range2.Values
    ' Consider checking that the two ranges are the same size
    For i = LBound(arr1, 1) To Ubound(arr1, 2)
    For j = LBound(arr1, 2) To Ubound(arr1, 2)
    If arr1(i, j) <> arr2(i, j) Then bMatchFail = True Exit For End If
    Next j
    If bMatchFail Then Exit For
    Next i
    Erase arr1 Erase arr2

    您会注意到此代码示例是通用的,适用于从任何位置获取的相同大小的两个范围 - 甚至来自单独的工作簿。如果您要比较两个相邻列,则加载一个包含两列的数组并比较IF arrX(i, 1) <> arrX(i,2) Then将使运行时减半。

    如果您从大范围内获取数以万计的数值,那么您的下一个挑战才有意义:对于任何小于此范围的数据,此扩展答案都没有性能提升。

    我们正在做的是:

    使用散列函数比较两个大范围的值

    这个想法很简单,虽然基础数学对于非数学家来说非常具有挑战性:我们不是一次比较一个值,而是运行一个数学函数,将值“散列”为一个简短的标识符,以便于比较。 / p>

    如果您要将范围与“参考”副本进行比较,则可以存储“引用”哈希值,这会将工作量减半。

    有一些快速可靠的散列函数,它们在Windows中作为安全和加密API的一部分提供。它们运行在字符串上有一个小问题,我们有一个数组可以工作;但您可以轻松找到一个快速的“Join2D”函数,该函数从范围的.Value2属性返回的2D数组中获取字符串。

    因此,两个大范围的快速比较函数将如下所示:

    Public Function RangeCompare(Range1 as Excel.Range, Range2 As Excel.Range) AS Boolean
    ' Returns TRUE if the ranges are identical.
    ' This function is case-sensitive.
    ' For ranges with fewer than ~1000 cells, cell-by-cell comparison is faster
    ' WARNING: This function will fail if your range contains error values.
    RangeCompare = False
    If Range1.Cells.Count <> Range2.Cells.Count Then RangeCompare = False ElseIf Range1.Cells.Count = 1 then RangeCompare = Range1.Value2 = Range2.Value2 Else RangeCompare = MD5(Join2D(Range1.Value2)) = MD5(Join2D(Range2.Value2)) Endif
    End Function

    我在这个VBA函数中包装了Windows System.Security MD5哈希:

    Public Function MD5(arrBytes() As Byte) As String
    ' Return an MD5 hash for any string
    ' Author: Nigel Heffernan Excellerando.Blogspot.com
    ' Note the type pun: you can pass in a string, there's no type conversion or cast ' because a string is stored as a Byte array and VBA recognises this.
    oMD5 As Object 'Set a reference to mscorlib 4.0 to use early binding

    Dim HashBytes() As Byte Dim i As Integer

    Set oMD5 = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider") HashBytes = oMD5.ComputeHash_2((arrBytes))
    For i = LBound(HashBytes) To UBound(HashBytes) MD5 = MD5 & Right("00" & Hex(HashBytes(i)), 2) Next i

    Set oMD5 = Nothing ' if you're doing this repeatedly, declare at module level and persist Erase HashBytes

    End Function
    还有其他VBA实现,但似乎没有人知道字节数组/字符串类型双关语 - 它们不是等价,它们相同 - 所以每个人都编码不必要类型转换。

    2015年快速而简单的Join2D功能为posted by Dick Kusleika on Daily Dose of Excel

    Public Function Join2D(ByVal vArray As Variant, Optional ByVal sWordDelim As String = " ", Optional ByVal sLineDelim As String = vbNewLine) As String
    
        Dim i As Long, j As Long
        Dim aReturn() As String
        Dim aLine() As String
    
        ReDim aReturn(LBound(vArray, 1) To UBound(vArray, 1))
        ReDim aLine(LBound(vArray, 2) To UBound(vArray, 2))
    
        For i = LBound(vArray, 1) To UBound(vArray, 1)
            For j = LBound(vArray, 2) To UBound(vArray, 2)
                'Put the current line into a 1d array
                aLine(j) = vArray(i, j)
            Next j
            'Join the current line into a 1d array
            aReturn(i) = Join(aLine, sWordDelim)
        Next i
    
        Join2D = Join(aReturn, sLineDelim)
    
    End Function
    

    如果您需要在进行比较之前删除空白行,则需要Join2D function I posted in StackOverflow back in 2012

    此类哈希比较最常见的应用是电子表格控件 - 更改监控 - 您会看到使用Range1.Formula代替Range1.Value2:但您的问题是关于比较价值而不是公式。