TOP

VBA-수업 13.3. 배열 사용(Arrays)(연습)

배열 사용을 연습하기 위해 배열의 속도 이점을 단계별로 보여주기 위해 사용한 매크로의 자체 버전을 만들어 보겠습니다.


이 연습의 시작점은 다음과 같습니다(데이터세트가 1000행으로 줄어든 것을 볼 수 있습니다).

여기서 Excel 예제 파일을 다운로드할 수 있습니다: arrays_exercise.xls

연습 목표: 프로시저는 루프를 사용하여 데이터 세트의 데이터를 처리하고 각 연도 및 각 고객 번호에 대해 YES 또는 NO 응답 수를 계산하고(사용자의 선택에 따라 YES 또는 NO) 이 수량을 입력해야 합니다. 워크시트의 지정된 셀에

"DS" 워크시트의 데이터를 배열에 저장하려면 다음 매크로를 완성하십시오.

Sub actualize()
     Dim last_row As Integer
     
     '데이터 세트의 마지막 행
     '...
        
     '동적 배열에 데이터 세트 저장
     Dim array_db()
     '...
        
End Sub

다음은 한 가지 솔루션 예시입니다.

Sub actualize()
     Dim last_row As Integer
     
     '데이터베이스의 마지막 줄
     last_row = Sheets("DS").Range("A1").End(xlDown).Row

     '동적 배열에 데이터 세트 저장
     Dim array_db()
     ReDim array_db(last_row - 2, 2)
     
     For row_number = 2 To last_row
         array_db(row_number - 2, 0) = Sheets("DS").Range("A" & row_number)
         array_db(row_number - 2, 1) = Sheets("DS").Range("B" & row_number)
         array_db(row_number - 2, 2) = Sheets("DS").Range("C" & row_number)
     Next
End Sub

이는 기본적으로 이전 강의에서 했던 작업을 반복합니다.

하지만 이제 다음 작업을 추가하여 매크로를 수정해야 합니다.

  • 사용자의 선택("예" 또는 "아니요")을 결정합니다.
  • 배열의 크기를 결정하기 위해 데이터 세트에서 "YES" 또는 "NO" 응답의 수를 계산합니다(Redim).
  • 배열에 "YES" 또는 "NO"라는 대답이 포함된 데이터 세트의 행만 저장합니다. 즉, 세 번째 열의 데이터를 저장할 필요가 없습니다.
  • 다음은 한 가지 솔루션 예시입니다.

    Sub actualize()
         Dim last_row As Integer, search_value As String, insert_row As Integer, value_yes_no As String, rows_number As Integer
         
         '데이터베이스의 마지막 줄
         last_row = Sheets("DS").Range("A1").End(xlDown).Row
    
         '검색 값(YES 또는 NO)
         If Sheets("RES").OptionButton_yes.Value = True Then
             search_value = "YES"
         Else
             search_value = "NO"
         End If
         
         '응답 수 YES 또는 NO
         rows_number = WorksheetFunction.CountIf(Sheets("DS").Range("C2:C" & last_row), search_value)
         
         '데이터 세트를 배열에 저장
         Dim array_db()
         ReDim array_db(rows_number - 1, 1)
    
         insert_row = 0
         
         For row_number = 2 To last_row
             value_yes_no = Sheets("DS").Range("C" & row_number)
             
             If value_yes_no = search_value Then
                 array_db(insert_row, 0) = Sheets("DS").Range("A" & row_number)
                 array_db(insert_row, 1) = Sheets("DS").Range("B" & row_number)
                 insert_row = insert_row + 1
             End If
         Next
    End Sub
    

    사용자 선택에 의한 검색은 절차 시작 시 다음 코드에 의해 결정됩니다.

     '검색 값(YES 또는 NO)
     If Sheets("RES").OptionButton_yes.Value = True Then
         search_value = "YES"
     Else
         search_value = "NO"
     End If
    

    CountIF 함수를 사용하여 "YES" 또는 "NO" 응답 수를 결정합니다.

     '응답 수 YES 또는 NO
     rows_number = WorksheetFunction.CountIf(Sheets("DS").Range("C2:C" & last_row), search_value)
    

    배열은 YES 또는 NO 응답 수에 맞게 크기가 조정되었으며 두 개의 열로 축소되었습니다.

    ReDim array_db(rows_number - 1, 1)
    

    이제 이 데이터는 세 번째 열이 사용자의 선택과 일치할 때 배열에 저장됩니다.

     '배열에 숫자 삽입
     insert_row = 0
    
     '데이터 세트 처리
     For row_number = 2 To last_row
         'C열 값(YES 또는 NO)
         value_yes_no = Sheets("DS").Range("C" & row_number)
         
         '값이 사용자의 선택과 일치하면 문자열이 배열에 저장됩니다.
         If value_yes_no = search_value Then
             'A 열에 값 저장
             array_db(insert_row, 0) = Sheets("DS").Range("A" & row_number)
             'B 열에 값 저장
             array_db(insert_row, 1) = Sheets("DS").Range("B" & row_number)
             '한 행이 저장되었습니다 => 배열의 삽입 번호가 1씩 증가합니다
             insert_row = insert_row + 1
         End If
     Next
    

    우리 배열에는 우리가 관심 있는 데이터만 포함되어 있습니다.

    이제 남은 일은 다음과 같습니다.

  • 2개의 루프를 사용하여 "RES" 워크시트에 있는 테이블의 각 요소를 처리합니다(체커보드 연습과 동일한 개념).
  • 각 셀의 각 고객 번호별로 매년 이 시트에 총 발생 횟수를 삽입하십시오.
  • 다음은 한 가지 솔루션 예시입니다.

     '응답 수 "YES"/"NO"
     For no_years = 2011 To 2026
         For no_client = 1 To 30
             counter = 0
             
             For i = 0 To UBound(array_db)
                 If Year(array_db(i, 0)) = no_years And array_db(i, 1) = no_client Then
                     counter = counter + 1
                 End If
             Next
             
             Cells(no_years - 2009, no_client + 1) = counter
         Next
     Next
    

    자세히 설명하는 댓글의 문제를 해결했습니다.

     '각 행에 대한 루프
     For no_years = 2011 To 2026
     
         '각 열에 대한 루프
         For no_client = 1 To 30
             '카운터 재설정
             counter = 0
             
             '어레이 처리
             For i = 0 To UBound(array_db)
                 '테이블의 행이 연도 및 고객 번호와 일치하는지 확인
                 If Year(array_db(i, 0)) = no_years And array_db(i, 1) = no_client Then
                     '연도와 고객 번호가 일치하면 카운터가 1 증가합니다.
                     counter = counter + 1
                 End If
             Next
             
             '배열을 처리한 후 결과가 해당 셀에 입력됩니다.
             Cells(no_years - 2009, no_client + 1) = counter
         Next
     Next
    

    마지막으로 전체 매크로에 대한 코드는 다음과 같습니다.

    Sub actualize()
         Dim last_row As Integer, search_value As String, insert_row As Integer, value_yes_no As String, rows_number As Integer, counter As Integer
         
         '콘텐츠 삭제
         Range("B2:AE17").ClearContents
         
         '데이터 세트의 마지막 행
         last_row = Sheets("DS").Range("A1").End(xlDown).Row
    
         '검색 값(YES 또는 NO)
         If Sheets("RES").OptionButton_yes.Value = True Then
             search_value = "YES"
         Else
             search_value = "NO"
         End If
         
         '응답 수 YES 또는 NO
         rows_number = WorksheetFunction.CountIf(Sheets("DS").Range("C2:C" & last_row), search_value)
         
         '배열에 값 저장
         Dim array_db()
         ReDim array_db(rows_number - 1, 1)
    
         insert_row = 0
         
         For row_number = 2 To last_row
             value_yes_no = Sheets("DS").Range("C" & row_number)
             
             If value_yes_no = search_value Then
                 array_db(insert_row, 0) = Sheets("DS").Range("A" & row_number)
                 array_db(insert_row, 1) = Sheets("DS").Range("B" & row_number)
                 insert_row = insert_row + 1
             End If
         Next
         
         '답변 계산 YES 또는 NO
         For no_years = 2011 To 2026
             For no_client = 1 To 30
                 counter = 0
                 
                 For i = 0 To UBound(array_db)
                     If Year(array_db(i, 0)) = no_years And array_db(i, 1) = no_client Then
                         counter = counter + 1
                     End If
                 Next
                 Cells(no_years - 2009, no_client + 1) = counter
             Next
         Next
    End Sub
    

    여기서 Excel 예제 파일을 다운로드할 수 있습니다: arrays_exercise_completed.xls