본문 바로가기

excel vba 시작하기

배열을 시트로 출력 방법

배열을 시트내 특정 위치로 출력하기 위해 우선은 배열의 크기를 계산할 수 있어야 합니다. 그리고 배열을 선언하는 방법 또는 배열 차원을 미리 고려해서 계산할 필요가 있었습니다.

 

[test1]

   우선 아래 코드는 Array() 함수를 사용하여 변수 Arr 을 배열로 초기화 한 뒤 시트내 "I1" 으로 출력한 것이다.

Sub test1()
    Dim Arr As Variant
    Arr = Array("가", "나", "다")
    
    Range("I1") = Arr
End Sub

[문제점1] 기대 결과인 I1 에는 "가", J1 에는 "나", K1 에는 "다" 와 달리, "가" 만 출력되었다.

test1() 실행 결과

 

[test2] 문제점1 해결 방법 구글링 결과

   구글링을 해보니 Range.Resize() 함수를 사용해야 할 것 같은데, 첫 번째 인수가 Range 의 행 크기, 두 번째 인수가 Range 의 열 크기를 지정해야 한다. 배열의 형태가 1X3 이므로 Range("I1").resize(1,3) 으로 설정하고 출력을 해 보니 아래 test2() 실행 결과와 같이 I1 에는 "가", J1 에는 "나", K1 에는 "다"로 예상 했던 결과를 얻을 수 있었다.

Sub test2()
    Dim Arr As Variant
    Arr = Array("가", "나", "다")
    
    Range("I1").Resize(3, 1) = Arr
    Range("I1").Resize(1, 3) = Arr
End Sub

[문제점2] 배열 처리를 위해 배열의 행 크기와 열 크기를 상수 지정에서 변수 지정으로 변경하는 방법을 해결해야 한다.

test2() 실행 결과

 

[test3] 문제점2 해결 방법 구글링 결과

   구글링을 해보니 배열함수인 UBound() 함수와 LBound() 함수를 사용하여 배열의 크기를 파악할 수 있다고 한다. 실제 평가를 해보니 Array() 함수를 사용하여 배열 값을 초기화한 경우 열의 크기는 알 수 있는데, 행의 크기를 알 수 없었다. 물론 1차원 배열을 정의했기 때문이다. 

Sub test3()
    Dim Arr As Variant
    Arr = Array("가", "나", "다")
    
    Dim size As Integer
    
    size = UBound(Arr)
    Debug.Print size
    size = UBound(Arr, 1)
    Debug.Print size
    On Error GoTo oneDimension
    size = UBound(Arr, 2)
    Debug.Print size
    
oneDimension:
    Debug.Print "1차원 배열입니다."

End Sub

[문제점3] 배열의 크기 계산는 사전에 배열의 차원을 미리 고려해서 구현해야 한다.

test3() 실행 결과

 

[test4] 문제점3 해결 방법 구현 결과

   처리할 배열의 차원이 1차원 배열인데, 2차원 배열 크기 계산을 시도하면 에러를 발생하기 때문에 이를 이용하여 구현해 보았다. 참고로 배열함수인 UBound(), LBound()는 index 가 0에서 시작한다는 것을 주의할 필요가 있다.

Sub test4()
    Dim Arr As Variant
    Arr = Array("가", "나", "다")
    
    Dim size_rows As Integer
    Dim size_columns As Integer

On Error GoTo oneDimension
    size_columns = UBound(Arr, 2) - LBound(Arr, 2) + 1
    Debug.Print "2차원 배열 크기: "; size_columns
    
oneDimension:
    size_rows = UBound(Arr, 1) - LBound(Arr, 1) + 1
    Debug.Print "1차원 배열 크기: "; size_rows


End Sub

[문제점4] Array() 함수를 사용하여 다차원 배열 초기화를 어떻게 할 수 있을까?

test4() 실행 결과

 

 

[test5] 문제점4 해결 방법 구글링 결과

   Array() 함수를 사용하여 2차원 배열로 생성할 방법을 고민하면서 구글링해 보았는데, 찾아 볼 수 없었다. 다만 수 차례 맨 땅에 헤딩해 가면서 코딩을 해 본 결과 "2차원 배열 같은 1차원 배열"로 초기화 할 수 있었다.

Sub test5()
    Dim Arr As Variant
    ReDim Arr(1 To 2)
    Arr(1) = Array("가", "나", "다")
    Arr(2) = Array("갸", "냐", "댜")
    
    Dim size_rows As Integer
    Dim size_columns As Integer

On Error GoTo oneDimension
    size_columns = UBound(Arr, 2) - LBound(Arr, 2) + 1
    Debug.Print "2차원 배열 크기: "; size_columns
    
oneDimension:
    size_rows = UBound(Arr, 1) - LBound(Arr, 1) + 1
    Debug.Print "1차원 배열 크기: "; size_rows


End Sub

[문제점5] 2차원 또는 다차원 배열 초기화를 어떻게 할 수 있을까?

test5() 실행 결과

 

 

[test6] 문제점5 해결 방법 구글링 결과

  배열 선언, 2차원 배열 재정의 후 2차원 배열을 초기화해 보았다. 결론적으로 Array() 함수와 같이 직관적으로 초기화할 수 있는 방법을 찾지는 못했다. 그리고 차선의 방법은 시트 내에서 초기값을 정의하고 이를 배열로 가져오는 방법을 사용해야 할 것 같다. 이 방법의 문제는 누군가/언젠가 시트를 수정하면 배열값도 변경이 되는 문제를 갖고 있다. 추후 포스팅 과제다. ㅠㅠ

배열의 행의 크기(개수)는 1차원으로 계산할 수 있고, 열의 크기(개수)는 2차원으로 계산할 수 있다.

Sub test6()
    Dim Arr As Variant
    ReDim Arr(1 To 2, 1 To 3)
    Arr(1, 1) = "가"
    Arr(1, 2) = "나"
    Arr(1, 3) = "다"
    Arr(2, 1) = "갸"
    Arr(2, 2) = "냐"
    Arr(2, 3) = "댜"
    
    Dim size_rows As Integer
    Dim size_columns As Integer

On Error GoTo oneDimension
    size_columns = UBound(Arr, 2) - LBound(Arr, 2) + 1
    Debug.Print "2차원 배열 크기: "; size_columns
    
oneDimension:
    size_rows = UBound(Arr, 1) - LBound(Arr, 1) + 1
    Debug.Print "1차원 배열 크기: "; size_rows


End Sub

[문제점6] 문제점 보다는 이제는 배열의 크기를 계산할 수 있게 되었으니, 시트로 출력하는 구현하는 일만 남았다.

test6() 실행 결과

 

[test7] 배열을 시트로 출력한 결과

  [test1], [test2] 이후 [test3]~[test6] 과정을 거치면서 다차원 배열을 시트로 출력할 수 있게 되었다. 이제는 다차원 배열에서 특정한 열 또는 행을 출력할 수 있을 것 같다. (이것도 다음에 포스팅 ㅎㅎ)

Sub test7()
    Dim Arr As Variant
    ReDim Arr(1 To 2, 1 To 3)
    Arr(1, 1) = "가"
    Arr(1, 2) = "나"
    Arr(1, 3) = "다"
    Arr(2, 1) = "갸"
    Arr(2, 2) = "냐"
    Arr(2, 3) = "댜"
    
    Dim size_rows As Integer
    Dim size_columns As Integer

On Error GoTo oneDimension
    size_columns = UBound(Arr, 2) - LBound(Arr, 2) + 1
    Debug.Print "2차원 배열 크기: "; size_columns
    
oneDimension:
    size_rows = UBound(Arr, 1) - LBound(Arr, 1) + 1
    Debug.Print "1차원 배열 크기: "; size_rows


    Range("I1").Resize(size_rows, size_columns) = Arr

End Sub

[문제점7] Array() 함수를 사용한 경우 시트로 출력할 수 있는 방법은?

test7() 실행 결과

 

 

[test8] Array() 함수로 구현된 배열을 시트로 출력한 결과

  [test5]에서 Array() 함수로 구현된 2차원 배열은 엑셀에서는 실제 1차원 배열로 처리하고 있음을 알 수 있었다. 따라서 사람에게는 2차원 배열로 인식되지만 실제는 1차원 배열이므로 Range.Resize() 함수를 사용할 때 1차원으로 처리하고, 행의 개수만큼 반복처리를 해 주면 된다.

Sub test8()
    Dim Arr As Variant
    ReDim Arr(1 To 2)
    Arr(1) = Array("가", "나", "다")
    Arr(2) = Array("갸", "냐", "댜")
    
    Dim size_rows As Integer
    Dim size_columns As Integer

On Error GoTo oneDimension
    size_columns = UBound(Arr, 2) - LBound(Arr, 2) + 1
    Debug.Print "2차원 배열 크기: "; size_columns
    
oneDimension:
    size_rows = UBound(Arr, 1) - LBound(Arr, 1) + 1
    Debug.Print "1차원 배열 크기: "; size_rows
    size_columns = UBound(Arr(1), 1) - LBound(Arr(1), 1) + 1
    Debug.Print "2차원 배열 크기: "; size_columns

    Range("I6").Resize(1, size_columns) = Arr(1)
    Range("I7").Resize(1, size_columns) = Arr(2)

End Sub

[문제점8] Array() 함수로 처리한 2차원 같은 1차원 배열과 실제 2차원 배열를 혼용할 경우 어떻게 처리하면 좋을까?

test8() 실행 결과

 

 

[test9] 2차원 같은 1차원 배열과 2차원 배열을 혼용할 경우

  다양한 배열 처리 함수를 필요에 따라 사용자함수로 만들게 되는데, 가능한 혼용하지 않고 한 가지로 정해서 사용하는 것이 정신 건강에 좋을 듯하다. 만약,, 만약의 경우를 고려해서 아래와 같이 배열 크기 계산을 구현해 보았다.

 

Sub test9()
    Dim Arr As Variant
    ReDim Arr(1 To 2)
    Arr(1) = Array("가", "나", "다")
    Arr(2) = Array("갸", "냐", "댜")
    
    Dim size_rows As Integer: size_rows = -1
    Dim size_elements As Integer: size_elements = -1
    Dim size_columns As Integer: size_columns = -1

On Error GoTo multiElement
    size_columns = UBound(Arr, 2) - LBound(Arr, 2) + 1
    Debug.Print "2차원 배열 크기: "; size_columns
    
multiElement:
On Error GoTo oneDimension
    size_elements = UBound(Arr(1), 1) - LBound(Arr(1), 1) + 1
    Debug.Print "1차원 요소 수: "; size_elements
    
oneDimension:
    size_rows = UBound(Arr, 1) - LBound(Arr, 1) + 1
    Debug.Print "1차원 배열 크기: "; size_rows

    If size_columns <> -1 Then
        Range("I1").Resize(size_rows, size_columns) = Arr
    ElseIf size_elements <> -1 Then
        Range("I6").Resize(1, size_elements) = Arr(1)
        Range("I7").Resize(1, size_elements) = Arr(2)
    Else
        Range("I1").Resize(size_rows, 1) = Arr
    End If

End Sub

[문제점9] 위의 예제처럼 1차원 배열 그리고 배열 크기를 2 이상으로 선언한 경우는 문제없이 실행되지만, 배열크기를 1개로 선언할 경우 에러를 유발합니다. (다음 포스팅 숙제)

test9() 실행 결과

 

해결할 문제들이 계속 있네요...

배열을 시트로 출력할 때 재사용할 만한 코드는 [test7] 입니다.

 

오늘은 여기까지 하겠습니다. 지루할 수 있는 글을 읽어 주셔서 감사합니다.

'excel vba 시작하기' 카테고리의 다른 글

엑셀 매크로 - 배열 함수  (0) 2020.12.12