2010-01-29 2 views
0

중복 행을 강조 표시하는 VBA를 사용하는 Excel의 프로 시저에서 작업하고 있습니다. 이 프로시 저는 행이 중복되었는지 판별하기 위해 워크 시트 함수 sumproduct의 결과를 평가합니다. Excel에서 중복 된 항목을 검색 할 때 숨겨진 행을 제외 할 수 있습니까?

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

지금까지 절차가 잘 작동하지만, 나는 그것이 평가에서 숨겨진 행과 열을 무시해야합니다

평가 된 공식은 다음과 같이 찾고 끝납니다. Range.Hidden = False을 사용하여 루프의 열에 숨겨진 행을 건너 뛸 수 있지만 SUMPRODUCT에서 숨겨진 행과 열을 제외하는 방법을 찾지 못했습니다.

두 개의 중첩 된 루프를 사용하여 두 번 반복하면서 한 번에 두 행의 값을 비교해 보았지만 N-squared 또는 O (n) 이터 레이션이 발생하여 포기했습니다. 그 방법.

스프레드 시트 수식 SUBTOTAL에서와 같이 SUMPRODUCT를 숨겨진 행을 무시하도록 강요 할 수 있습니까?

여기는 내가 지금까지 가지고있는 것입니다 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 

답변

1

RowHeight/Hidden 속성은 어떤 공식에도 노출되지 않습니다. 솔루션은 VBA에 있어야합니다. 이것을 달성하는 한 가지 방법은 원하는대로하는 UDF (User Defined Formula)를 작성한 다음, 사용자 정의 수식에 사용하는 것입니다.

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)) 
+0

으시시. 이 스레드에서 다시 확인하기 전에 이미이 경로를 시작했습니다. 필자가 작성한 UDF는 귀하의 것과 거의 동일합니다. 1 & & 0 &에서 "&"의 의미는 무엇입니까? – Kuyenda

+0

형식 선언 문자로 문자 "1"을 Long 형식으로 강제 설정합니다. 리터럴에 넣지 않으면 VBA는 Integer, Long 또는 Double 중 가장 작은 것을줍니다. VB의 기본 유형은 길기 때문에 모든 명령문 (예 : Redim/For 등)은 long (그러므로 1s)을 사용합니다. 또한 비교는 동일한 유형으로 암시 적 변환을 수행해야합니다. 행 높이가 길기 때문에 0에 추가 했으므로 암시 적 변환을 수행 할 필요가 없습니다. 이는 미세 최적화이며 측정 가능한 차이를 만들어 내지 못할 것입니다. 그것은 단지 습관과 개인 스타일입니다. 단지 ... 더 ... – Oorang

+0

리터럴을 입력하는 것이 중요합니다. 16 진수 또는 16 진수 상수를 사용할 때 부호가 없기 때문에 숫자가 바뀌면 VBA가 올바르게 변환되지 않습니다. 특정 범위에 있습니다 (2^16 번째 구체적으로 : http://support.microsoft.com/kb/38888). 요약하면, 당신은 정말로 그걸 필요로하지 않습니다. 나는 단지 거기에 넣었습니다 : – Oorang

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 
관련 문제