Excel VBA脚本比较两组数据和ID排列

时间:2014-02-12 21:51:52

标签: excel vba excel-vba permutation

我正在整理一个比较两列数据(每行大约15,000行)的VBA脚本,并确定是否有任何单元格是另一个单元格的排列。

例如,如果A1 = 15091且B52 = 19510,则该函数会将它们识别为具有相同的字符集。

我有一个循环设置,它检查A列中的每个单独的单元格与B列中的每个其他单元格以及循环中的各种函数,但到目前为止,在完成此任务的任何内容中都不成功。

此外,由于“数字”格式化的单元格将在小数点后丢弃所有零,因此15091.1将不会被识别为与15091.01相同的字符集。

1 个答案:

答案 0 :(得分:1)

您可以使用纯Excel方法在没有VBA的情况下执行此操作。 (虽然找到下面的VBA解决方案)想法是为每个值构建一种“哈希值”,对于一组数字的每个排列都是相同的 - 不与其他哈希重叠。

要做的就是:

  1. 计算每个数字0-9的数量(例如15091和19510将是1x0,2x1,1x5和1x9)
  2. 将每个计数乘以10 ^位(例如1 * 10 ^ 0 = 1,2 * 10 ^ 1 = 20,1 * 10 ^ 5 = 100000,1x10 ^ 9 = 1000000000)
  3. 总结这些产品,(例如1000100021)
  4. 然后,您需要做的就是将这些哈希相互匹配(使用Excel的MATCH函数)并查看是否找到了某些内容(使用ISERROR函数)。

    Excel的逐步说明(假设您的数据位于Sheet1和Sheet2,A列,从A1开始:

    1. 在Sheet1中:
    2. 在顶部插入两行
    3. 在B3中,放置此公式=TEXT(A3,"0") - 这将删除每个数字的余数并将其转换为文本。将公式复制到范围的最后
    4. 在C1:L1中,放置数字0,1,2,......
    5. 在C2:L2中,放置公式=10^C1
    6. 在C3中,放置此公式:=LEN($B3)-LEN(SUBSTITUTE($B3,C$1,"")) - 并将其复制到右侧,直到列L,然后向下复制到列表的末尾。这将计算位数
    7. 在M3中,放置此公式:=SUMPRODUCT(C3:L3,$C$2:$L$2) - 这将计算哈希值
    8. 重复Sheet2中的步骤2-7
    9. 在Sheet1中,将此公式放在N3中:=NOT(ISERROR(MATCH(M3,Sheet2!$M:$M,0)))
    10. 完成!

      这是一个VBA解决方案:

      Option Explicit
      
      Sub IdentifyMatches()
          Dim rngKeys As Range, rngToMatch As Range, rngCell As Range
          Dim dicHashes As Object
          'the range you want to have highlighted in case of a match
          Set rngKeys = Sheets("Sheet1").Range("A3:A5")
      
          'the range to search for matches
          Set rngToMatch = Sheets("Sheet2").Range("A3:A5")
      
          Set dicHashes = CreateObject("Scripting.Dictionary")
      
          'Create dictionary of hashes (dictionary is used for its .Exists property
          For Each rngCell In rngToMatch
              dicHashes(GetHash(rngCell)) = True
          Next
      
          'Check each cell in rngKey if it has a match
          For Each rngCell In rngKeys
              If dicHashes.Exists(GetHash(rngCell)) Then
                  'Action to take in case of a match
                  rngCell.Font.Bold = True
                  Debug.Print rngCell.Value & " has a match!"
              Else
                  rngCell.Font.Bold = False
              End If
          Next
      
      End Sub
      
      
      Function GetHash(rngValue As Range) As Long
          Dim strValue As String
          Dim i As Integer, digit As Integer
          Dim result As Long
          Dim digits(0 To 9) As Integer
      
          'Potentially add error check here
          strValue = Format(rngValue.Value, "0")
      
          For i = 1 To Len(strValue)
              digit = Int(Mid(strValue, i, 1))
              digits(digit) = digits(digit) + 1
          Next i
      
          For i = 0 To 9
              result = result + 10 ^ i * digits(i)
          Next i
      
          GetHash = result
      End Function
      

      最后但并非最不重要的是here's the example file