codememo

각 루프의 역순

tipmemo 2023. 4. 28. 20:38
반응형

각 루프의 역순

VB의 가장 강력한 기능 중 하나는 인덱스를 참조하지 않고 컬렉션의 개체를 순환할 수 있다는 것입니다.for each고리.

컬렉션에서 개체를 제거하는 것이 매우 유용합니다.

스프레드시트의 행과 같은 미리 정의된 개체를 제거할 때 인덱싱을 사용하고 최대로 시작하여 첫 번째 개체로 돌아가면 코드가 더 간단합니다(반복기를 사용하여 -1단계). (그렇지 않으면 각 개체에 대해 활성 개체가 삭제되면 열거자 포인터를 이전 개체로 다시 이동하므로 오프셋이 필요합니다)

예를 들면

For intA = 10 to 1 step -1 
    ' ...
Next

For Each | Next eg를 사용할 때는 어떻습니까?

For each rngCell in Selection.Cells
    ' ...
Next

내가 어떻게 그것을 사용하여 거꾸로 루프할 수 있습니까?for each루프 구문?

각 루프 구문에 대해 를 사용하여 거꾸로 루프할 수 없습니다.

대안으로 다음을 사용할 수 있습니다.For i = a To 1 Step -1루프:

Sub reverseForEach()
    Dim i As Long, rng As Range

    Set rng = ActiveSheet.Range("A1:B2")

    For i = rng.Cells.Count To 1 Step -1

        Debug.Print rng.item(i).Address
        ' Or shorthand rng(i) as the Item property 
        ' is the default property for the Range object.
        ' Prints: $B$2, $A$2, $B$1, $A$1

    Next i

End Sub

이 작업은 Item 속성이 있는 모든 컬렉션에서 작동합니다.예를 들어 워크시트, 영역 또는 도형입니다.

참고: Range 개체에서 사용할 때 루프의 순서는 오른쪽에서 왼쪽으로, 그 다음 위로 이동합니다.

내장 컬렉션용(예:Range) 짧은 대답은: 할 수 없습니다.사용자 정의 컬렉션의 경우 비용이 이점을 초과할 수 있지만 @VBlades에 의해 연결된 답변이 유용할 수 있습니다.

한 가지 해결 방법은 제거할 항목의 식별을 실제 제거와 분리하는 것입니다.예: 범위에 대해 다음을 사용하여 새 범위 변수를 작성합니다.Union그런 다음 해당 변수를 처리합니다(예: 모든 행을 한 번에 삭제).를 위해Range예를 들어, 당신은 또한 그것을 이용할 수 있습니다.Variant Array일을 더욱 빠르게 하는 방법.

이 중 하나라도 유용한지 여부는 실제 사용 사례에 따라 달라집니다.

다른 좋은 답변도 있지만 범위를 통해 "뒤로 이동"하는 또 다른 방법이 있습니다.


범위를 배열로 변환하는 기능

이 함수는 다음과 같이 사용할 수 있는 "역방향 범위 배열"을 반환합니다.For..Each:

Function ReverseRange(rg As Range) As Range()
    Dim arr() As Range, r As Long, c As Long, n As Long
    With rg
        ReDim arr(1 To .Cells.Count) 'resize Range Array
        For r = .Cells(.Rows.Count, 1).Row To .Cells(1, 1).Row Step -1
            For c = .Cells(1, .Columns.Count).Column To .Cells(1, 1).Column Step -1
                n = n + 1
                Set arr(n) = .Worksheet.Cells(r, c) 'set cell in Array
            Next c
        Next r
    End With
    ReverseRange = arr  'return Range Array as function result
End Function

사용 예:

Sub test()
    Dim oCell
    For Each oCell In ReverseRange(ActiveSheet.Range("E5:A1"))

        Debug.Print oCell.Address 'do something here with each cell

    Next oCell
End Sub

원하는 카운터로 설정된 두 번째 변수를 사용하고 코드에서 이 변수를 사용합니다.

'ex: Loop from n = 19 to 16
For i = 0 To 3
   n = 19 - i
   'your code here using n as the counter
Next

범위 컬렉션에만 해당됩니다.영역이 하나 이상인 경우 더 복잡합니다.

기본적으로 두 개의 루프가 있습니다. 첫 번째 루프는 배열에 있는 모든 셀의 인덱스를 유지하고 두 번째 루프는 뒤에서 앞으로 범위의 연합을 만듭니다.

Option Explicit

Private Sub Main()
    Dim InvertedRange As Range
    Set InvertedRange = InvertRange(Application.Union(ActiveSheet.Range("A1:A2"), _
      ActiveSheet.Range("F6:F7"), ActiveSheet.Range("E4:F5"), ActiveSheet.Range("E1")))
    Dim ActualRange As Range
    For Each ActualRange In InvertedRange
        Debug.Print (ActualRange.Address(False, False) & " : " & ActualRange.Value)
    Next ActualRange
End Sub

Public Function InvertRange(ByVal rngRange_I As Range) As Range
    Dim RangesArray() As Long
    ReDim RangesArray(1 To rngRange_I.Count, 1 To rngRange_I.Count)
    Dim ActualArea As Range
    Dim ActualRange As Range
    Dim ArrayIndex As Long
    For Each ActualArea In rngRange_I.Areas
        For Each ActualRange In ActualArea
            ArrayIndex = ArrayIndex + 1
            RangesArray(ArrayIndex, 1) = ActualRange.Row
            RangesArray(ArrayIndex, 2) = ActualRange.Column
        Next ActualRange
    Next ActualArea

    Dim ActualRow As Long
    Dim ActualColumn As Long
    ActualRow = RangesArray(UBound(RangesArray, 1), 1)
    ActualColumn = RangesArray(UBound(RangesArray, 2), 2)
    With rngRange_I.Worksheet
        Dim InvertedRange As Range
        Set InvertedRange = .Cells(ActualRow, ActualColumn)
        For ArrayIndex = UBound(RangesArray, 1) To LBound(RangesArray, 1) Step -1
            ActualRow = RangesArray(ArrayIndex, 1)
            ActualColumn = RangesArray(ArrayIndex, 2)
            Set InvertedRange = Application.Union(InvertedRange, _
              .Cells(ActualRow, ActualColumn))
        Next ArrayIndex
    End With

    Set InvertRange = InvertedRange
End Function

스택(LIFO 데이터 구조)을 사용하여 목록을 작성할 수 있으며 코드는 다음과 같습니다.

   Dim aStack as Object

   Set aStack = CreateObject("System.Collections.Stack") 
    
   For Each arngCell in Selection.Cells
       aStack.Push(arngCell)
   Next
    
   While aStack.Count > 0 
    
       rngCell = aStack.Pop

       ' ...
    
    End While 

    Set stack = Nothing

언급URL : https://stackoverflow.com/questions/24358183/reverse-order-of-for-each-loop

반응형