글목록

2021년 4월 4일

배열 데이터의 차원(Dimension) 확인하기 - 에러(Error) 활용

엑셀 시트로부터 Value를 읽어오면 기본적으로 2차원 행렬 형태의 배열이 만들어집니다.

즉 n행 x m열 개의 데이터를 배열 A에 읽어오면, A의 크기는 (1 to n, 1 to m)로 자동 지정됩니다. 만약 1개의 열 데이터를 가져온다면, (1 to n, 1 to 1), 1개의 행 데이터를 가져오면, (1 to 1, 1 to m) 배열을 자동으로 정의한 후 가져오는 것이지요.

그런데, 데이터 작업을 하다보면 꼭 2차원 배열을 만드는 것은 아닙니다. 예를 들면, Array 함수를 사용하여 1차원 배열을 만든다거나, 배열의 크기를 계속 변경해야해서 Redim을 사용할 목적으로 1차원 배열을 사용하는 경우도 있습니다.

이렇게 엑셀에서는 기본적으로 2차원 배열을 사용하는 반면, 코딩하는 데에는 1차원 배열로 변경했을 때 코드를 간결하게 만들 수도 있기 때문에 두 차원간의 데이터 변환이 필요한 경우가 있습니다.

2차원 데이터를 1차원 데이터로, 혹은 1차원 데이터를 2차원 데이터로 변환시켜야 하는 경우도 있습니다. 그런데, 데이터의 차원을 확인하는 방법이 없습니다. 아마 변수 선언은 기본적으로 인간이 하고, 그 차원을 확인할 필요가 없기 때문에 만들어두지 않은 모양입니다. 아니면 제가 알지 못하는 것일지도...

어쨋거나, 배열의 차원을 확인할 수 있다면, 배열 데이터를 다루는데 있어 조금더 매끄러운 처리가 가능해질 수 있습니다.


배열의 차원을 확인하는 방법은 VBA의 에러를 활용하는 것입니다.

Function GetArrayDim(iData()) As Integer
  On Error GoTo ErrorHandler
  Dim i As Integer, n As Integer
  i = 0
  Do
    i = i + 1
    n = UBound(iData, i)
  Loop While Err.Number = 0
ErrorHandler:
  GetArrayDim = i - 1
  Err.Clear
End Function

LBound(배열, i) 또는 UBound(배열, i)은 i차원 이상의 배열에서 i번째 차원의 배열 최소, 최대 index를 출력해주는 함수입니다. 만약, 배열의 차원이 i보다 작으면 Error가 발생하게 됩니다. 예를 들어, 3차원 배열이 입력되었는데 4번째 차원의 index를 출력하라고 하면 에러가 나는 것이지요.

위와 같이 GetArrayDim함수를 작성하고, 배열 데이터를 입력하게 되면, i를 하나씩 늘려서 i번째 차원의 최대 index를 찾으라고 하면, 입력된 배열 iData의 차원보다 i가 커질 때, Error를 발생시킵니다. 아무 Error가 없으면, Err.Number (에러코드)는 0이고, Err.Number가 0이 아니면 에러가 발생했다는 것으로 판단할 수 있습니다. 따라서, Err.Number=0이면 계속 1씩 증가시켜가면서 에러가 발생할 때까지 체크합니다.

첫줄에 선언한 On Error GoTo ErrorHandler 는 에러가 발생하면 ErrorHandler 라벨로 이동하라는 뜻입니다. (라벨은 개인적으로 작성하시면 됩니다.) On Error Resume Next (에러가 발생하면, 그 다음 단계를 실행하라) 사용하더라도 무방합니다. 어쨋거나 에러가 발생했을 때 어떻게 처리할 것인지 미리 선언해두어야 에러 메세지를 표시하지 않고 자동으로 처리해 줍니다. 이 코드를 삽입하지 않으면, 아래와 같이 에러 메세지가 발생하기 때문에 자연스럽게 처리가 되지 않습니다.

끝으로, 에러가 발생한 i값보다 1 작은 숫자가 배열의 차원이 되므로, 배열의 차원은 i-1로 반환해줍니다. 아래 Test를 실행해보면 4차원의 배열임을 확인할 수 있습니다. 만약, Redim 행을 생략해버린다면, 0 차원으로 출력하겠지요.

Sub Test()
  Dim tVec(), n As Integer, i As Integer
  ReDim tVec(1 To 1, 1, 3, 6)
  MsgBox GetArrayDim(tVec) & " 차원입니다."
End Sub

매크로를 짜다보면 무수한 에러와 마주하게 되고, 이러한 에러를 최소화하기 위해 무수한 디버깅을 하게되는데, 간혹 에러를 일부로 유도하여 유익하게 이용하는 경우도 있습니다. 다른 예로, 해당 문서 내에 어떠한 object가 존재하는지 체크하는 방법도 이처럼 에러를 활용할 수도 있습니다.

댓글 없음:

댓글 쓰기

의견이나 질문이 있으신 분은 언제든지 댓글을 달아주세요~

많이 본 글 :