尝试在列的每个单元格中查找重复的逗号分隔文本

Trying to find Duplicate comma delimited texts in each cell of a column

提问人:M Muaz 提问时间:5/6/2021 最后编辑:PᴇʜM Muaz 更新时间:5/7/2021 访问量:125

问:

我有从某人那里得到的以下宏,并试图修改它以适应我的目的。

我正在尝试更改此宏以查找并突出显示每个单元格中具有重复值的单元格, 例如,它应该突出显示 B62 和 B63(绿色), 并将重复值的颜色字体涂成红色(即 B62 中的 B_HWY_1010,B63 中的 B_HWY_1015)

enter image description here

Sub Dupes()
  Dim d As Object
  Dim a As Variant, itm As Variant
  Dim i As Long, k As Long
  Dim rng As Range
  Dim bColoured As Boolean
 
  Set d = CreateObject("Scripting.Dictionary")
  Set rng = Range("B1", Range("B" & Rows.Count).End(xlUp))
  a = rng.Value
  For i = 1 To UBound(a)
    For Each itm In Split(a(i, 1), ",")
      d(itm) = d(itm) + 1
    Next itm
  Next i
  Application.ScreenUpdating = False
  For i = 1 To UBound(a)
    k = 1
    bColoured = False
    For Each itm In Split(a(i, 1), ",")
      If d(itm) > 1 Then
        If Not bColoured Then
          rng.Cells(i).Interior.Color = vbGreen
          bColoured = True
        End If
        rng.Cells(i).Characters(k, Len(itm)).Font.Color = RGB(244, 78, 189)
      End If
      k = k + Len(itm) + 1
    Next itm
  Next i
  Application.ScreenUpdating = True
End Sub

任何帮助或建议都是值得赞赏的。

VBA 循环 重复 CSV

评论

0赞 FaneDuru 5/6/2021
“重复逗号分隔文本”是什么意思?只有一个分隔元素与另一个单元格中的另一个元素相同?还是整个字符串,即使它包含逗号分隔符也是相同的?
0赞 M Muaz 5/6/2021
@FaneDuru简单来说,我试图在单个单元格中查找重复项,而不是与任何其他单元格进行比较。因此,如果您查看帖子中的图像,第 62 行的值输入了两次,用逗号分隔,因此在这种情况下,我希望宏识别它并突出显示它
0赞 FaneDuru 5/6/2021
如果有两个这样的同义字符串(在一个单元格中)和第三个不同的字符串怎么办?它会被标记为重复吗?
0赞 M Muaz 5/6/2021
@FaneDuru是的,它也必须识别这一点。假设一个单元格有:A、B、C、B,那么它应该识别并突出显示第二个“B”
0赞 FaneDuru 5/6/2021
突出显示第二个“B”,还是正在讨论的单元格?绿色的内饰颜色在你的照片中意味着什么?

答:

2赞 Pᴇʜ 5/6/2021 #1

下面将执行此操作

Option Explicit

Public Sub Example()
    Dim Cell As Range
    For Each Cell In Range("A1:A10")
        HighlightRepetitions Cell, ", "
    Next Cell
End Sub

Private Sub HighlightRepetitions(ByVal Cell As Range, ByVal Delimiter As String)
    If Cell.HasFormula Or Cell.HasArray Then Exit Sub ' don't run on formulas

    Dim Dict As Object
    Set Dict = CreateObject("Scripting.Dictionary")
    
    Dim Data() As String
    Data = Split(Cell.Value, Delimiter)  ' split data in the cell by Delimiter 
    
    Dim StrLen As Long  ' length of the string that was already processed
    
    Dim i As Long
    For i = LBound(Data) To UBound(Data)  ' loop through all data items
        Dim DataLen As Long
        DataLen = Len(Data(i))  'get length of current item
        
        If Dict.Exists(Data(i)) Then
            ' item is a repetition: color it
            Cell.Characters(StrLen + 1, DataLen).Font.Color = vbRed
            Cell.Interior.Color = vbGreen
        Else
            ' item is no repetition: add it to the dictionary
            Dict.Add Data(i), Data(i)
        End If
        
        StrLen = StrLen + DataLen + Len(Delimiter)  ' calculate the length of the processed string and add length of the delimiter
    Next i
End Sub

以下项目将着色:

enter image description here

您可以在循环之前关闭,并在循环之后打开以阻止其闪烁。请注意,这不会在 formuas 上运行,因为部分公式结果不能着色。这可以通过用作第一行来防止。ScreenUpdatingSub Example()If Cell.HasFormula Or Cell.HasArray Then Exit Sub

评论

0赞 FaneDuru 5/6/2021
好。。。投票赞成。我知道他想把这两种情况都加粗。
2赞 FaneDuru 5/6/2021 #2

请也尝试下一个代码:

Sub findComaDelDuplicates()
 Dim sh As Worksheet, arr, itm, arrInt, i As Long, rngS As Range, pos As Long
 Dim arrDif As Long, j As Long, startPos As Long, arrPos, k As Long, mtch
 
 Set sh = ActiveSheet
 With sh.Range("B1", Range("B" & sh.rows.count).End(xlUp))
    arr = .value               'put the range value in an array to make the iteration faster
    .ClearFormats            'clear previous format
    .Font.Color = vbBlack 'make the font color black
 End With
 
 For i = 1 To UBound(arr)           'iterate between the array elements:
    arrInt = Split(arr(i, 1), ",")       'split the content by comma delimiter
    ReDim arrPos(UBound(arrInt)) 'redim the array keeping elements already formatted
    For Each itm In arrInt            'iterate between the comma separated elements
        arrDif = UBound(arrInt) - 1 - UBound(Filter(arrInt, itm, False)) 'find how many times an element exists
        If arrDif > 0 Then            'if more then an occurrence:
            If rngS Is Nothing Then             'if range to be colored (at once) does not exist:
                Set rngS = sh.Range("B" & i)  'it is crated
            Else
                Set rngS = Union(rngS, sh.Range("B" & i)) 'a union is made from the previous range and the new one
            End If
            mtch = Application.match(itm, arrPos, 0)       'check if the itm was already processed:
            If IsError(mtch) Then                                'if itm was not processed:
                For j = 1 To arrDif + 1                          'iterate for number of occurrences times
                    If j = 1 Then startPos = 1 Else: startPos = pos + 1 'first time, inStr starts from 1, then after the first occurrence
                    pos = InStr(startPos, sh.Range("B" & i).value, itm)  'find first character position for the itm to be colored
                    sh.Range("B" & i).Characters(pos, Len(itm)).Font.Color = vbRed 'color it
                Next j
                arrPos(k) = itm      'add the processed itm in the array
            End If
        End If
    Next
    Erase arrInt                      'clear the array for the next cell value
 Next i
 If Not rngS Is Nothing Then rngS.Interior.Color = vbGreen        'color the interior cells of the built range
End Sub

注意:上面的代码将范围放在数组中,以便更快地迭代。但是,如果区域不是从第一行开始的,则必须通过将行添加到区域的第一行来获取要处理的单元格。代码可以调整以建立这种关联,但我现在懒得这样做......:)i

评论

1赞 Pᴇʜ 5/6/2021
干得好,看起来这也行得通。它只是为第一次重复着色。取而代之的是,将第一个颜色留成黑色,给其他颜色,给第一个颜色,把最后一个留成黑色。• 他说你的颜色是第一个B,而不是第二个。• 但实际上很高兴在答案中涵盖两种方式。A, B, C, B then it should identify and highlight the 2nd "B"
0赞 M Muaz 5/6/2021
太好了,这个也很好用。谢谢你们俩
0赞 FaneDuru 5/6/2021
没有优化,只测试了一次,它适用于我的样品,没有尝试不同的变体,现在我正在开车...... :)
1赞 FaneDuru 5/7/2021
@P ᴇʜ:更改了代码逻辑,以便将所有重复出现的项颜色为红色。
0赞 FaneDuru 5/7/2021
@M Muaz:更改了代码逻辑,以便将所有重复出现的出现颜色为红色。它也应该足够快,可以进行大范围的测量。