我想检查excel中相应单元格中文本的相似性

我想检查excel中相应单元格中文本的相似性,excel,vba,similarity,Excel,Vba,Similarity,我的excel工作表中有一个数据集,每个单元格中的数据是一组以“;”分隔的数字 预期结果是在第二个单元格中,所有四个数字都在两列(G和H)中,但顺序不同。在下一行中,顺序相同。那么,有没有办法检查相似性呢 我试过使用下面的代码,但它似乎只突出显示(红色)前几个字符 代码是: Sub highlight() Dim xRg1 As Range Dim xRg2 As Range Dim xTxt As String Dim xCell1 As Range

我的excel工作表中有一个数据集,每个单元格中的数据是一组以“;”分隔的数字

预期结果是在第二个单元格中,所有四个数字都在两列(G和H)中,但顺序不同。在下一行中,顺序相同。那么,有没有办法检查相似性呢

我试过使用下面的代码,但它似乎只突出显示(红色)前几个字符

代码是:

Sub highlight()
    Dim xRg1 As Range
    Dim xRg2 As Range
    Dim xTxt As String
    Dim xCell1 As Range
    Dim xCell2 As Range
    Dim I As Long
    Dim J As Integer
    Dim xLen As Integer
    Dim xDiffs As Boolean
    On Error Resume Next
    If ActiveWindow.RangeSelection.Count > 1 Then
      xTxt = ActiveWindow.RangeSelection.AddressLocal
    Else
      xTxt = ActiveSheet.UsedRange.AddressLocal
    End If
lOne:
    Set xRg1 = Application.InputBox("Range A:", "Similarity finder", xTxt, , , , , 8)
    If xRg1 Is Nothing Then Exit Sub
    If xRg1.Columns.Count > 1 Or xRg1.Areas.Count > 1 Then
        MsgBox "Multiple ranges or columns have been selected ", vbInformation, "Similarity finder"
        GoTo lOne
    End If
lTwo:
    Set xRg2 = Application.InputBox("Range B:", "Similarity finder", "", , , , , 8)
    If xRg2 Is Nothing Then Exit Sub
    If xRg2.Columns.Count > 1 Or xRg2.Areas.Count > 1 Then
        MsgBox "Multiple ranges or columns have been selected ", vbInformation, "Similarity finder"
        GoTo lTwo
    End If
    If xRg1.CountLarge <> xRg2.CountLarge Then
       MsgBox "Two selected ranges must have the same numbers of cells ", vbInformation, "Similarity finder"
       GoTo lTwo
    End If
    xDiffs = (MsgBox("Click Yes to highlight similarities, click No to highlight differences ", vbYesNo + vbQuestion, "Similarity finder") = vbNo)
    Application.ScreenUpdating = False
    xRg2.Font.ColorIndex = xlAutomatic
    For I = 1 To xRg1.Count
        Set xCell1 = xRg1.Cells(I)
        Set xCell2 = xRg2.Cells(I)
        If xCell1.Value2 = xCell2.Value2 Then
            If Not xDiffs Then xCell2.Font.Color = vbRed
        Else
            xLen = Len(xCell1.Value2)
            For J = 1 To xLen
                If Not xCell1.Characters(J, 1).Text = xCell2.Characters(J, 1).Text Then Exit For
            Next J
            If Not xDiffs Then
                If J <= Len(xCell2.Value2) And J > 1 Then
                    xCell2.Characters(1, J - 1).Font.Color = vbRed
                End If
            Else
                If J <= Len(xCell2.Value2) Then
                    xCell2.Characters(J, Len(xCell2.Value2) - J + 1).Font.Color = vbRed
                End If
            End If
        End If
    Next
    Application.ScreenUpdating = True
End Sub
子高亮显示()
调光xRg1作为范围
Dim xRg2 As范围
Dim xTxt作为字符串
Dim xCell1 As范围
Dim xCell2 As范围
我想我会坚持多久
作为整数的Dim J
作为整数的Dim-xLen
作为布尔值的Dim-xdiff
出错时继续下一步
如果ActiveWindow.RangeSelection.Count>1,则
xTxt=ActiveWindow.RangeSelection.AddressLocal
其他的
xTxt=ActiveSheet.UsedRange.AddressLocal
如果结束
孤独的:
设置xRg1=Application.InputBox(“范围A:”、“相似性查找器”、xTxt、、8)
如果xRg1为空,则退出Sub
如果xRg1.Columns.Count>1或xRg1.Areas.Count>1,则
MsgBox“已选择多个范围或列”,vbInformation,“相似性查找器”
独行侠
如果结束
lTwo:
设置xRg2=Application.InputBox(“范围B:,”相似性查找器“,”,,,,8)
如果xRg2为空,则退出Sub
如果xRg2.Columns.Count>1或xRg2.Areas.Count>1,则
MsgBox“已选择多个范围或列”,vbInformation,“相似性查找器”
后藤酒店
如果结束
如果xRg1.CountLarge xRg2.CountLarge,则
MsgBox“两个选定区域必须具有相同数量的单元格”,vbInformation,“相似性查找器”
后藤酒店
如果结束
xDiffs=(MsgBox(“单击是以突出显示相似性,单击否以突出显示差异”,vbYesNo+vbQuestion,“相似性查找器”)=vbNo)
Application.ScreenUpdating=False
xRg2.Font.ColorIndex=xlAutomatic
对于I=1到xRg1。计数
设置xCell1=xRg1。单元格(I)
设置xCell2=xRg2。单元格(I)
如果xCell1.Value2=xCell2.Value2,则
如果不是xDiffs,则xCell2.Font.Color=vbRed
其他的
xLen=Len(xCell1.Value2)
对于J=1至xLen
如果不是xCell1.Characters(J,1).Text=xCell2.Characters(J,1).Text,则退出
下一个J
如果不是xdiff那么
如果j1那么
xCell2.Characters(1,J-1).Font.Color=vbRed
如果结束
其他的

如果J一种方法是使用第一列创建正则表达式,并对第二列应用它

使用regex的一个优点是,返回的数据之一是匹配的开始和长度——非常适合寻址range对象的characters属性

我使用了早期绑定(请参阅代码注释中要设置的引用),但是如果必须的话,可以使用后期绑定

我也有A列和B列中的数据,但您可以使用定义数据位置的代码部分来更改这些数据

您不需要在出现错误时使用任何
代码。编写代码来处理任何可预见的错误要好得多。我没有做任何错误检查,这可能需要添加

如果速度是一个问题,可以进行其他各种修改

构造的正则表达式将具有

\b(?:nnn | nnn | nnn | nnn)\b

这意味着

  • 匹配单词边界
  • 匹配任何管道分隔的子字符串
  • 匹配另一个单词边界
有关详细信息,请参阅


一种方法是使用第一列创建正则表达式,并对第二列应用它

使用regex的一个优点是,返回的数据之一是匹配的开始和长度——非常适合寻址range对象的characters属性

我使用了早期绑定(请参阅代码注释中要设置的引用),但是如果必须的话,可以使用后期绑定

我也有A列和B列中的数据,但您可以使用定义数据位置的代码部分来更改这些数据

您不需要在出现错误时使用任何
代码。编写代码来处理任何可预见的错误要好得多。我没有做任何错误检查,这可能需要添加

如果速度是一个问题,可以进行其他各种修改

构造的正则表达式将具有

\b(?:nnn | nnn | nnn | nnn)\b

这意味着

  • 匹配单词边界
  • 匹配任何管道分隔的子字符串
  • 匹配另一个单词边界
有关详细信息,请参阅

相似之处
  • 您的数据有问题:列
    a
    中的值以“;”结尾,而列
    B
    中的值以“;”结尾。给出的解决方案是只使用最后一个分号前面的字符串
    Split
    功能进行编码>
  • 为了避免复杂性,我将代码集成到您相当酷的解决方案中
代码

Option Explicit

Sub highlightOrig()
    Dim xRg1 As Range
    Dim xRg2 As Range
    Dim xTxt As String
    Dim xCell1 As Range
    Dim xCell2 As Range
    Dim I As Long
    Dim J As Integer
    Dim xLen As Integer
    Dim xDiffs As Boolean
    On Error Resume Next
    If ActiveWindow.RangeSelection.Count > 1 Then
      xTxt = ActiveWindow.RangeSelection.AddressLocal
    Else
      xTxt = ActiveSheet.UsedRange.AddressLocal
    End If
lOne:
    Set xRg1 = Application.InputBox("Range A:", "Similarity finder", xTxt, , , , , 8)
    If xRg1 Is Nothing Then Exit Sub
    If xRg1.Columns.Count > 1 Or xRg1.Areas.Count > 1 Then
        MsgBox "Multiple ranges or columns have been selected ", vbInformation, "Similarity finder"
        GoTo lOne
    End If
lTwo:
    Set xRg2 = Application.InputBox("Range B:", "Similarity finder", "", , , , , 8)
    If xRg2 Is Nothing Then Exit Sub
    If xRg2.Columns.Count > 1 Or xRg2.Areas.Count > 1 Then
        MsgBox "Multiple ranges or columns have been selected ", vbInformation, "Similarity finder"
        GoTo lTwo
    End If
    If xRg1.CountLarge <> xRg2.CountLarge Then
       MsgBox "Two selected ranges must have the same numbers of cells ", vbInformation, "Similarity finder"
       GoTo lTwo
    End If
    xDiffs = (MsgBox("Click Yes to highlight similarities, click No to highlight differences ", vbYesNo + vbQuestion, "Similarity finder") = vbNo)
    Application.ScreenUpdating = False
    
    xRg1.Font.ColorIndex = xlAutomatic
    xRg2.Font.ColorIndex = xlAutomatic
    
    Const Delimiter As String = "; "
    Dim dLen As Long: dLen = Len(Delimiter)
    Dim s() As String
    Dim d() As String
    Dim cString As String
    Dim n As Long
    Dim cStart As Long
    
    If Not xDiffs Then
        For I = 1 To xRg1.Count
            cStart = 1
            Set xCell1 = xRg1.Cells(I)
            Set xCell2 = xRg2.Cells(I)
            cString = Left(xCell1.Value, InStrRev(xCell1.Value, ";") - 1)
            s = Split(cString, Delimiter)
            cString = Left(xCell2.Value, InStrRev(xCell2.Value, ";") - 1)
            d = Split(cString, Delimiter)
            For n = 0 To UBound(d)
                If IsNumeric(Application.Match(d(n), s, 0)) Then
                    xCell2.Characters(cStart, Len(d(n))).Font.Color = vbRed
                End If
                cStart = cStart + Len(d(n)) + dLen
            Next n
        Next I
    Else
        For I = 1 To xRg1.Count
            cStart = 1
            Set xCell1 = xRg1.Cells(I)
            Set xCell2 = xRg2.Cells(I)
            cString = Left(xCell1.Value, InStrRev(xCell1.Value, ";") - 1)
            s = Split(cString, Delimiter)
            cString = Left(xCell2.Value, InStrRev(xCell2.Value, ";") - 1)
            d = Split(cString, Delimiter)
            For n = 0 To UBound(d)
                If IsError(Application.Match(d(n), s, 0)) Then
                    xCell2.Characters(cStart, Len(d(n))).Font.Color = vbRed
                End If
                cStart = cStart + Len(d(n)) + dLen
            Next n
        Next I
    End If
    
    Application.ScreenUpdating = True

End Sub
选项显式
次高亮显示()
调光xRg1作为范围
Dim xRg2 As范围
Dim xTxt作为字符串
Dim xCell1 As范围
Dim xCell2 As范围
我想我会坚持多久
作为整数的Dim J
作为整数的Dim-xLen
作为布尔值的Dim-xdiff
出错时继续下一步
如果ActiveWindow.RangeSelection.Count>1,则
xTxt=ActiveWindow.RangeSelection.AddressLocal
其他的
xTxt=ActiveSheet.UsedRange.AddressLocal
如果结束
孤独的:
设置xRg1=Application.InputBox(“范围A:”、“相似性查找器”、xTxt、、8)
如果xRg1为空,则退出Sub
如果xRg1.Columns.Count>1或xRg1.Areas.Count>1,则
MsgBox“已选择多个范围或列”,vbInformation,“Simi”
Option Explicit

Sub highlightOrig()
    Dim xRg1 As Range
    Dim xRg2 As Range
    Dim xTxt As String
    Dim xCell1 As Range
    Dim xCell2 As Range
    Dim I As Long
    Dim J As Integer
    Dim xLen As Integer
    Dim xDiffs As Boolean
    On Error Resume Next
    If ActiveWindow.RangeSelection.Count > 1 Then
      xTxt = ActiveWindow.RangeSelection.AddressLocal
    Else
      xTxt = ActiveSheet.UsedRange.AddressLocal
    End If
lOne:
    Set xRg1 = Application.InputBox("Range A:", "Similarity finder", xTxt, , , , , 8)
    If xRg1 Is Nothing Then Exit Sub
    If xRg1.Columns.Count > 1 Or xRg1.Areas.Count > 1 Then
        MsgBox "Multiple ranges or columns have been selected ", vbInformation, "Similarity finder"
        GoTo lOne
    End If
lTwo:
    Set xRg2 = Application.InputBox("Range B:", "Similarity finder", "", , , , , 8)
    If xRg2 Is Nothing Then Exit Sub
    If xRg2.Columns.Count > 1 Or xRg2.Areas.Count > 1 Then
        MsgBox "Multiple ranges or columns have been selected ", vbInformation, "Similarity finder"
        GoTo lTwo
    End If
    If xRg1.CountLarge <> xRg2.CountLarge Then
       MsgBox "Two selected ranges must have the same numbers of cells ", vbInformation, "Similarity finder"
       GoTo lTwo
    End If
    xDiffs = (MsgBox("Click Yes to highlight similarities, click No to highlight differences ", vbYesNo + vbQuestion, "Similarity finder") = vbNo)
    Application.ScreenUpdating = False
    
    xRg1.Font.ColorIndex = xlAutomatic
    xRg2.Font.ColorIndex = xlAutomatic
    
    Const Delimiter As String = "; "
    Dim dLen As Long: dLen = Len(Delimiter)
    Dim s() As String
    Dim d() As String
    Dim cString As String
    Dim n As Long
    Dim cStart As Long
    
    If Not xDiffs Then
        For I = 1 To xRg1.Count
            cStart = 1
            Set xCell1 = xRg1.Cells(I)
            Set xCell2 = xRg2.Cells(I)
            cString = Left(xCell1.Value, InStrRev(xCell1.Value, ";") - 1)
            s = Split(cString, Delimiter)
            cString = Left(xCell2.Value, InStrRev(xCell2.Value, ";") - 1)
            d = Split(cString, Delimiter)
            For n = 0 To UBound(d)
                If IsNumeric(Application.Match(d(n), s, 0)) Then
                    xCell2.Characters(cStart, Len(d(n))).Font.Color = vbRed
                End If
                cStart = cStart + Len(d(n)) + dLen
            Next n
        Next I
    Else
        For I = 1 To xRg1.Count
            cStart = 1
            Set xCell1 = xRg1.Cells(I)
            Set xCell2 = xRg2.Cells(I)
            cString = Left(xCell1.Value, InStrRev(xCell1.Value, ";") - 1)
            s = Split(cString, Delimiter)
            cString = Left(xCell2.Value, InStrRev(xCell2.Value, ";") - 1)
            d = Split(cString, Delimiter)
            For n = 0 To UBound(d)
                If IsError(Application.Match(d(n), s, 0)) Then
                    xCell2.Characters(cStart, Len(d(n))).Font.Color = vbRed
                End If
                cStart = cStart + Len(d(n)) + dLen
            Next n
        Next I
    End If
    
    Application.ScreenUpdating = True

End Sub
Function Sort(A As Variant) As Variant
    Dim sorted As Variant, item As Variant
    Dim lb As Long, ub As Long
    Dim i As Long
    Dim items As Object
    Set items = CreateObject("System.Collections.ArrayList")
    
    lb = LBound(A)
    ub = UBound(A)
    ReDim sorted(lb To ub)
    
    For i = lb To ub
        item = A(i) 'Somewhat oddly, seems needed
        items.Add item
    Next i
    
    items.Sort
    
    For i = lb To ub
        sorted(i) = items(i - lb)
    Next i
    
    Sort = sorted
End Function

Function Similar(s1 As String, s2 As String) As Boolean
    Similar = (Join(Sort(Split(s1, ";")), ";") = Join(Sort(Split(s2, ";")), ";"))
End Function