2010-06-24 3 views
4

배경왜 for for 루프는 전체 데이터 세트를 처리하지 않습니까?

이벤트에 대한 티켓 할당 스프레드 시트가 있습니다. 스프레드 시트의 각 행에 할당 된 티켓의 이름과 개수가 있습니다. 각각의 이름은 별도의 행에 티켓에 한 번 중복 될 수 있도록

The Spreadsheet http://s3.amazonaws.com/twitpic/photos/full/120237739.png?AWSAccessKeyId=0ZRYP5X5F6FSMBCCSE82&Expires=1277404609&Signature=pGRx%2Fxcm3InEY2PyKd3k09hC7Xo%3D

나는이 같은 스프레드 시트를 변경해야

The Spreadsheet after changes http://s3.amazonaws.com/twitpic/photos/full/120238390.png?AWSAccessKeyId=0ZRYP5X5F6FSMBCCSE82&Expires=1277404546&Signature=xrUAdzyIJWKGnrge%2FCD4EudiyX8%3D

나는 그것이 그러나,이 작업을 수행하는 매크로를 이상한 행동

에게 문제

,691,363 전시210

매크로가 전체 데이터 세트를 반복하지 않습니다. 코드를 살펴보면 의도적으로 LastRow의 값을 증가 시켰음에도 불구하고 For 루프 만 지정된 원래 값만큼 반복됩니다. 각 반복 끝에 새로운 값 LastRow은 무시됩니다. 루프가 잘 작동하는 동안

이의 (a 마십시오 루프 동안을 사용하여 작업 코드는 아래를 참조)에 해당하는 않는 한 특별히 이상한 것 같다

[질문

이유는 무엇입니까 문제 섹션에서 설명하는 동작 (위)가 발생하고 왜 등가 구조와 모순 되는가?

매크로 루프

Sub InsertSurnames() 

    Dim LastRow As Long 
    Dim r As Long 
    Dim surname As String 
    Dim tickets As Integer 
    Dim surnameCol As Integer 
    Dim ticketCol As Integer 
    Dim targetCol As Integer 

    surnameCol = 1 
    ticketCol = 3 
    targetCol = 4 
    LastRow = ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row 

    For r = 1 To LastRow 

     surname = Cells(r, surnameCol).Value 
     tickets = Cells(r, ticketCol).Value 


     If (Not (Len(surname) = 0)) Then 

      Cells(r, targetCol).Value = surname 

      For x = 1 To tickets - 1 

       Cells(r + x, 1).EntireRow.Insert 
       Cells(r + x, targetCol).Value = surname 



      Next x 

      LastRow = LastRow + tickets - 1 

     End If 


    Next r 

End Sub 

에 대한 마 루프

Sub InsertSurnames() 

    Dim LastRow As Long 
    Dim r As Long 
    Dim surname As String 
    Dim tickets As Integer 
    Dim surnameCol As Integer 
    Dim ticketCol As Integer 
    Dim targetCol As Integer 

    surnameCol = 1 
    ticketCol = 3 
    targetCol = 4 
    LastRow = ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row 
    r = 1 

    Do While r <= LastRow 

     surname = Cells(r, surnameCol).Value 
     tickets = Cells(r, ticketCol).Value 


     If (Not (Len(surname) = 0)) Then 

      Cells(r, targetCol).Value = surname 

      For x = 1 To tickets - 1 

       Cells(r + x, 1).EntireRow.Insert 
       Cells(r + x, targetCol).Value = surname 



      Next x 

      LastRow = LastRow + tickets - 1 

     End If 

     r = r + 1 
    Loop 

End Sub 

답변

7

컴파일러는 'For'Loop 구문을 다르게 interpere하고 다른 어셈블리 호출을 사용하여 임시 변수를 CPU 캐시에 배치하므로 각 반복 후에 변수를 읽으려면 RAM으로 돌아갈 필요가 없습니다. 그냥 CPU의 캐시에서 그것을 잡을 수 있습니다. 이것은 의도적으로 성능을 높이기 위해 'For'루프가 'While'루프보다 일반적으로 빠른 이유입니다. 'for'루프의 한계 변수는 여전히 메모리에 있지만 각 반복 중에 읽지는 않습니다. 따라서 원래 상한을 설정하는 데 사용 된 변수를 변경하면 루프가 여전히 원래 경계로 실행됩니다. While 루프는 각 반복에서 exit 절을 검사하고 캐시하지 않습니다. 일반적으로 'For'루프는 루프 반복이 필요한 횟수가있을 때 while 루프와 반대되는 반면, 루프를 반복해야하는 횟수를 잘 모르는 경우에는 더 많은 동적 제어가 필요합니다.

1

매크로이 VB에서 설계된다. for 루프의 한계는 루프의 시작 직전에 한 번만 계산되어 임시 변수에 저장됩니다. 따라서 한계를 계산하는 변수의 값을 변경하면 임시 변수는 영향을받지 않습니다. 이것은 예기치 않은 효과가 발생하지만 제한이 한 번만 계산되므로이 계산에 사용 된 모든 메서드는 한 번만 입력되므로 잠재적으로 루프를 빠르게 수행 할 수 있습니다.

+0

다른 루프 구성 요소간에 일관성이 없다는 것은 여전히 ​​이상한 일입니다. – chrisbunney

3

For...Next 루프를 계속 사용하려면, 당신은 할 수 :

For r = LastRow To 1 Step -1 
    surname = Cells(r, surnameCol).Value 
    tickets = Cells(r, ticketCol).Value 

    If (Not (Len(surname) = 0)) Then 
     Cells(r, targetCol).Value = surname 

     For x = 1 To tickets - 1 
      Cells(r + x, 1).EntireRow.Insert 
      Cells(r + x, targetCol).Value = surname 
     Next x 

     LastRow = LastRow + tickets - 1 
    End If 
Next r 

삽입하거나 루프 내부에서 Worksheet에 행을 삭제하려는 모든 시간을, 그것은 결국 직장에서 시작하는 것이 좋습니다 뒤로. 이것은 대부분의 경우 루프 인덱스를 조정할 필요가 없다는 것을 의미합니다.

관련 문제