我正在使用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
答案 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