2010년 10월 29일 금요일

클래스 모듈을 이용하여 리스트 데이터구조 만들어 사용하기

VBA편집기에서 클래스모듈을 삽입한 후, 속성창에서 이름을 LIstItem으로 바꾼다. 이 이름은 다르게 작성해도 되나, 아래 클래스모듈에도 이를 반영하여 변경시켜주어야 한다.

클래스모듈 - 이 부문은 그대로 복사해서 사용해도 잘 작동한다(msdn에서 가져온 것임)

Public Value As Variant
Public NextItem As ListItem
Dim liHead As ListItem

Function Search(ByVal varItem As Variant, _
 ByRef liCurrent As ListItem, ByRef liPrevious As ListItem) _
 As Boolean
    Dim fFound As Boolean
    fFound = False
    Set liPrevious = Nothing
    Set liCurrent = liHead
    Do While Not liCurrent Is Nothing
        With liCurrent
            If varItem > .Value Then
                Set liPrevious = liCurrent
                Set liCurrent = .NextItem
            Else
                Exit Do
            End If
        End With
    Loop
    ' You can't compare the value in liCurrent to the sought
    ' value unless liCurrent points to something.
    If Not liCurrent Is Nothing Then
        fFound = (liCurrent.Value = varItem)
    End If
    Search = fFound
End Function

Public Sub Add(varValue As Variant)
    Dim liNew As New ListItem
    Dim liCurrent As ListItem
    Dim liPrevious As ListItem
    liNew.Value = varValue
    ' Find where to put the new item. This function call
    ' fills in liCurrent and liPrevious.
    Call Search(varValue, liCurrent, liPrevious)
    If Not liPrevious Is Nothing Then
        Set liNew.NextItem = liPrevious.NextItem
        Set liPrevious.NextItem = liNew
    Else
        ' Inserting at the head of the list:
        ' Set the new item to point to what liHead currently
        ' points to (which might just be Nothing). Then
        ' make liHead point to the new item.
        Set liNew.NextItem = liHead
        Set liHead = liNew
    End If
End Sub

Public Function Delete(varItem As Variant) As Boolean
    Dim liCurrent As ListItem
    Dim liPrevious As ListItem
    Dim fFound As Boolean
    ' Find the item. This function call
    ' fills in liCurrent and liPrevious.
    fFound = Search(varItem, liCurrent, liPrevious)
    If fFound Then
        If Not liPrevious Is Nothing Then
             ' Deleting from the middle or end of the list.
             Set liPrevious.NextItem = liCurrent.NextItem
        Else
            ' Deleting from the head of the list.
            Set liHead = liCurrent.NextItem
        End If
    End If
    Delete = fFound
End Function

Public Sub DebugList()
    ' Print the list to the Immediate window.
    Dim liCurrent As ListItem
    Set liCurrent = liHead
    Do While Not liCurrent Is Nothing
        Debug.Print liCurrent.Value
        Set liCurrent = liCurrent.NextItem
    Loop
End Sub
Source : http://msdn.microsoft.com/en-us/library/aa227565(VS.60).aspx

위에서 작성된 클래스를 일반 모듈에서 사용하려면 다음과 같이 한다.

일반모듈

Sub TestList()
    Dim liTest As New ListItem   '여기서 ListItem은 클래스모듈 이름이다
    For i = 2 To 1000   '2부터 1000까지 리스트에 추가한다.
      liTest.Add i 
    Next   
    Call liTest.DebugList   'ListItem 클래스의 DebugList 메서드를 호출한다. 즉 리스트를 화면인쇄한다.
    Debug.Print "=== 끝 ^_^ ==="  
End Sub

배열의 크기가 long 이상의 크기(2,147,483,647)를 초과하면 오버플로가 발생하여 에러가 나듯이, 이 VBA 리스트도 상당히 큰 갯수를 추가하면 스택 오버플로가 발생하여 에러가 나는 것 같다. (정확히 어는 숫자를 초과해야 하는지는 테스트 해보지 않아서 확실하지 않다) 또한 정확한 테스트는 해보지 않았지만, 실행하면서 느끼는 체감으로는 아이템 갯수가 늘어나면 배열보다 더 느려지고 처리시간이 많이 걸리는 것 같다.

어떻게 하면 VBA에서 매우 큰 갯수(예를들면 6천억개)의 데이터 아이템을 넣을 수 있는 자료구조를 만들어 사용할 수 있을까?

댓글 없음:

댓글 쓰기

2.1 벡터(Vector)

  R의 자료구조 : 벡터, factor, 행렬, 배열, 데이터프레임, 리스트 벡터(Vector)는 동일한 형태(예, 숫자)의 데이터 구성인자가 1개 이상이면서 1차원으로 구성되어 있는 데이터 구조입니다. w <- c(1, 2, 3, 4, ...