改进"查找重复项",但条件格式不起作用

时间:2015-09-28 09:37:23

标签: excel vba excel-vba

我希望使用条件格式来标记重复项,但我想在多列中查找重复项并标记条目,而不管副本位于哪一列。这在本质上不受我支持。找到了,所以我制作了自己的UDF。本帖子底部列出的代码。

问题在于,虽然UDF按预期工作,但我无法让CF工作。

我有一个CF,我根据同一行但不同列的值格式化某些单元格,并且我已经使用公式=INDIRECT("Z" & ROW()) <> 0取得了巨大的成功。在此基础上,我为UDF尝试了以下内容:

=findCandidatesForDuplicate(ADDRESS(ROW(); COLUMN(); 4))
=findCandidatesForDuplicate("B" & ROW())

但是这段代码没有给出任何格式 - 没有任何格式。应用范围为$B$2:$B$4000,因为这是我想要标记的唯一范围。我尝试在传递字符串到传递范围之间更改UDF和CF输入,但我没有做任何事情来应用格式化。

我假设因为没有应用格式化,UDF不会在预期的选定单元格上运行,我再次假设这是因为无法让Excel理解我希望它如何解析CF输入。

在工作表中,对于我知道重复的第14行,我可以输入=findCandidatesForDuplicate("B14"),单元格将显示TRUE
同样,我可以输入=findCandidatesForDuplicate(ADDRESS(ROW(B14); COLUMN(B14);4)),它也会显示TRUE

问题可归结为:我如何使条件格式引擎理解我想要做的事情(将UDF与规则所应用范围内的每个单元格作为参数运行并标记相应的单元格在B)栏中?

这是功能代码。基本上,如果一行在列出的任何列中找到重复的条目,则该行被视为重复。

Function findCandidatesForDuplicate(rngStr As String, Optional countOnly As Boolean, Optional dbg As Boolean) As Variant
Dim rng As Range
Dim colA As Range, searchString As String, result As Long
Dim ws As Worksheet, tbl As ListObject

Set ws = Application.ThisWorkbook.Worksheets(1)
Set tbl = ws.ListObjects("Tabell1")

Set rng = ws.Range(rngStr)
Set colA = Range("A" & rng.Row)

For i = 3 To 5

    searchString = colA.Offset(0, i - 1).Value
    If searchString = "" Then GoTo NextIteration

    'Set rng = Range(rng.Address, tbl.ListColumns(i).DataBodyRange.Address) ' Only searches downwards from input range
    Set rng = Range(tbl.ListColumns(i).DataBodyRange.Address) ' Searches the entire column
    result = Application.WorksheetFunction.CountIf(rng, "=" & searchString)

    If result > 1 Then
        If dbg = True Then Debug.Print "Found result in loop no. " & i - 2 & ", matching on value " & searchString
        Exit For
    End If

NextIteration:
Next i

If countOnly = True And result > 1 Then
    findCandidatesForDuplicate = result
ElseIf countOnly = True Then
    findCandidatesForDuplicate = 0
ElseIf result > 1 Then
    findCandidatesForDuplicate = True
Else
    findCandidatesForDuplicate = False
End If

End Function

1 个答案:

答案 0 :(得分:0)

我还没有找到为什么这不起作用,也没有找到如何使工作,所以这是一个解决方法:

使用UDF调用自己的行填充一些远端列,然后使用=INDIRECT("AAA" & ROW()) = whateverValueSetByUDF作为公式,使CF在触发UDF的单元格上显示选定的格式。

它不够优雅,并且每次更改时都需要在包含UDF结果的列上进行列范围的手动文本到列更新(过滤表将正常工作,但如果更改排序,则必须按照描述进行更新)...但只要您知道如何使用表格,它就会起作用。

另外,我修改了代码,以便为如何格式化行提供更多选项。使用这种输出方式,除了查找可能重复的行外,您还可以突出显示哪些列正在触发。

用法:使用上述INDIRECT公式,根据您的具体设置进行调整。我建议将=<>设置为resultWhereString值之一。

Function findCandidatesForDuplicate(rng As Range, Optional countOnly As Boolean, Optional dbg As Boolean) As Variant
Dim colA As Range, searchString As String, result As Long, resultWhereString As String
Dim ws As Worksheet, tbl As ListObject

Set ws = Application.ThisWorkbook.Worksheets(1)
Set tbl = ws.ListObjects("Table1")
Set colA = Range("A" & rng.Row)

For i = 3 To 5

    searchString = colA.Offset(0, i - 1).Value
    ' --> You can add more criteria here
    If searchString = "" Or searchString = "myEmail@domain.com" Then GoTo NextIteration

    Set rng = Range(tbl.ListColumns(i).DataBodyRange.Address) ' Searches the entire column
    result = Application.WorksheetFunction.CountIf(rng, "=" & searchString)

    If result > 1 Then
        If dbg = True Then Debug.Print "Found result in loop no. " & i - 2 & ", matching on value " & searchString

        Select Case i
            ' --> Update this loop if the range of i changes
            Case 3
                resultWhereString = "ResultCol1"
            Case 4
                resultWhereString = "ResultCol2"
            Case 5
                resultWhereString = "ResultCol3"
        End Select

        Exit For
    End If

NextIteration:
Next i

If countOnly = True And result > 1 Then
    findCandidatesForDuplicate = result
ElseIf countOnly = True Then
    findCandidatesForDuplicate = 0
ElseIf result > 1 Then
    findCandidatesForDuplicate = resultWhereString
Else
    findCandidatesForDuplicate = ""
End If

End Function