在Excel中搜索重复项时是否可以排除隐藏的行?

时间:2010-01-29 22:50:13

标签: excel vba big-o quadratic

我正在使用VBA处理Excel中的过程,该过程突出显示重复的行。该过程评估工作表函数sumproduct的结果,以确定该行是否有重复。

评估的公式最终看起来像这样:

SUMPRODUCT(--(A1:A10 = A1), --(B1:B10 = B1), --(C1:C10 = C1))

到目前为止,该过程运行良好,但我需要它来忽略评估中隐藏的行和列。我可以使用Range.Hidden = False跳过循环中列中的隐藏行,但我还没有找到从SUMPRODUCT中排除隐藏行和列的方法。

我还尝试使用两个嵌套循环遍历每一行两次,只是一次比较两行的值,但这导致了N平方或O(n 2 )迭代,所以我放弃了这种方法。

有没有办法强制SUMPRODUCT忽略隐藏的行,电子表格公式SUBTOTAL可能会这样做?

以下是我到目前为止使用的Evaluate(SUMPRODUCT):谢谢!

Private Sub ShowDuplicateRows()

    Dim lngRow As Long
    Dim lngColumn As Long
    Dim strFormula As String

    With Selection

        For lngRow = 1 To .Rows.Count
            If Not .Rows(lngRow).Hidden Then

                strFormula = "SUMPRODUCT("
                For lngColumn = 1 To .Columns.Count
                    If Not .Columns(lngColumn).Hidden Then
                        If strFormula <> "SUMPRODUCT(" Then
                            strFormula = strFormula & ", "
                        End If
                        strFormula = strFormula _
                        & "--(" & .Columns(lngColumn).Address _
                        & " = " & .Cells(lngRow, lngColumn).Address & ")"
                    End If
                Next
                strFormula = strFormula & ")"

                If Evaluate(strFormula) > 1 Then
                    .Rows(lngRow).Font.Color = RGB(255, 0, 0)
                End If

            End If
        Next lngRow

    End With

End Sub

2 个答案:

答案 0 :(得分:1)

RowHeight / Hidden属性不会暴露给任何公式。解决方案必须在VBA中。实现此目的的一种方法是创建一个用户定义的公式(UDF),它可以满足您的需求,然后在您的sumproduct公式中使用它。

Public Function IsVisible(ByVal rng As Excel.Range) As Variant
    Dim varRtnVal As Variant
    Dim lRow As Long, lCol As Long
    Dim ws As Excel.Worksheet
    ReDim varRtnVal(1 To rng.Rows.Count, 1 To rng.Columns.Count)
    For lRow = 1& To rng.Rows.Count
        For lCol = 1& To rng.Columns.Count
            varRtnVal(lRow, lCol) = CDbl(-(rng.Cells(lRow, lCol).RowHeight > 0&))
        Next
    Next
    IsVisible = varRtnVal
End Function

然后你的公式看起来像这样:

=SUMPRODUCT(IsVisible($A$2:$A$11),--($A$2:$A$11=1),--($B$2:$B$11=1),--($C$2:$C$11=1))

答案 1 :(得分:0)

这是完整更新的代码。首先是主程序,然后是用户定义的函数。

如果有人能够解释为什么将嵌套循环放在UDF中比在主程序中使用它更快我会非常感激它!再次感谢Oorang!

我使我的IsVisible UDF版本更灵活一些。它可以使用作为参数传递的范围,或者如果没有传递,则使用Application.Caller

Private Sub ShowDuplicateRows()

    Dim lngRow As Long
    Dim lngColumn As Long
    Dim strFormula As String

    With Selection

        For lngRow = 1 To .Rows.Count
            If Not .Rows(lngRow).Hidden Then

                strFormula = "SUMPRODUCT(--(ISVISIBLE(" _
                & .Columns(1).Address & "))"
                For lngColumn = 1 To .Columns.Count
                    If Not .Columns(lngColumn).Hidden Then
                        strFormula = strFormula _
                        & ", --(" & .Columns(lngColumn).Address _
                        & " = " & .Cells(lngRow, lngColumn).Address & ")"
                    End If
                Next
                strFormula = strFormula & ")"

                If Evaluate(strFormula) > 1 Then
                    .Rows(lngRow).Font.Color = RGB(255, 0, 0)
                Else
                    .Rows(lngRow).Font.ColorIndex = xlAutomatic
                End If

            End If
        Next lngRow

    End With

End Sub

Public Function IsVisible(Optional ByVal Reference As Range) As Variant

    Dim varArray() As Variant
    Dim lngRow As Long
    Dim lngColumn As Long

    If Reference Is Nothing Then Set Reference = Application.Caller

    With Reference

        ReDim varArray(1 To .Rows.Count, 1 To .Columns.Count)

        For lngRow = 1 To .Rows.Count
            For lngColumn = 1 To .Columns.Count
                varArray(lngRow, lngColumn) _
                = Not .Rows(lngRow).Hidden _
                And Not .Columns(lngColumn).Hidden
            Next lngColumn
        Next lngRow

    End With

    IsVisible = varArray

End Function