엑셀 VBA 강좌(8): 엑셀 VBA 언어 기본-자료형(Data type), 자료구조(Data structure)

이번 글은 엑셀 VBA 언어 기본 중 자료형(Data type)과 제공되는 자료구조(Data structure)에 대해 살펴본다.

이전 글에서 이어지는 내용이다.

엑셀 VBA 강좌(7): 엑셀 VBA 언어 기본-문법(Syntax)

3.3. 자료형

3.3.1. 기본 자료형

VB(또는 VBA)에서 지원하는 자료형을 요약하면 다음 표와 같다. 아래 출처의 표 내용중 Collection, Dictionary는 “자료 구조”에서 별도로 설명한다.

기본 자료형 목록

출처: https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/data-type-summary

데이터 형식저장 용량범위
Boolean2 bytesTrue 또는 False
Byte1 byte0 ~ 255
CollectionUnknownUnknown
Currency (scaled integer)8 bytes-922,337,203,685,477.5808 ~ 922,337,203,685,477.5807
Date8 bytesJanuary 1, 100, to December 31, 9999
(100-01-01 ~ 9999-12-31)
Decimal14 bytes+/-79,228,162,514,264,337,593,543,950,335 with no decimal point

+/-7.9228162514264337593543950335 with 28 places to the right of the decimal

Smallest non-zero number is+/-0.0000000000000000000000000001
DictionaryUnknownUnknown
Double (double-precision floating-point)8 bytes-1.79769313486231E308 to -4.94065645841247E-324 for negative values

4.94065645841247E-324 to 1.79769313486232E308 for positive values
Integer2 bytes-32,768 to 32,767
Long (Long integer)4 bytes-2,147,483,648 to 2,147,483,647
LongLong (LongLong integer)8 bytes-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

Valid on 64-bit platforms only.
LongPtr (Long integer on 32-bit systems, LongLong integer on 64-bit systems)4 bytes on 32-bit systems

8 bytes on 64-bit systems
-2,147,483,648 to 2,147,483,647 on 32-bit systems

-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 on 64-bit systems
Object4 bytesAny Object reference
Single (single-precision floating-point)4 bytes-3.402823E38 to -1.401298E-45 for negative values

1.401298E-45 to 3.402823E38 for positive values
String (variable-length)10 bytes + string length0 to approximately 2 billion
String (fixed-length)Length of string1 to approximately 65,400
Variant (with numbers)16 bytesAny numeric value up to the range of a Double
Variant (with characters)22 bytes + string length (24 bytes on 64-bit systems)Same range as for variable-length String
User-defined (using Type)Number required by elementsThe range of each element is the same as the range of its data type.

이 중에서 가장 자주 사용하는 데이터 형식은 Int, Long, String, Boolean 정도이다.

Variant, User-defined 데이터 형식에 대해 아래에 추가로 설명한다.

Variant 데이터 형식

Variant 데이터 형식은 여러 데이터 형식을 저장하고 처리할 수 있는 특별한 데이터 형식이다. 변수를 선언할 때 데이터 형식을 생략하면 Variant 데이터 형식으로 지정된다. Variant 데이터 형식에 대한 자세한 내용은 아래 URL을 참고하기 바란다.

https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/variant-data-type

실행중에 Variant 변수가 어떤 데이터 형식을 저장하고 있는지 확인하려면 VarType 함수를 이용한다.

https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/vartype-function

구문

VarType(varname)

필수 요소인 varname 인수는 사용자 정의 형식의 변수를 제외한 변수가 들어 있는 Variant입니다.

반환형식

상수설명
vbEmpty0Empty(초기화되지 않음)
vbNull1Null(유효한 데이터 없음)
vbInteger2정수
vbLong3긴 정수
vbSingle4단정도 부동 소수점 수
vbDouble5배정도 부동 소수점 수
vbCurrency6통화값
vbDate7날짜값
vbString8문자열
vbObject9개체
vbError10오류값
vbBoolean11Boolean 값
vbVariant12Variant(variant 배열에서만 사용)
vbDataObject13데이터 액세스 개체
vbDecimal14십진값
vbByte17바이트값
vbArray8192배열

나는 개인적으로 Variant 데이터 형식을 잘 사용하지 않고 시트 데이터를 한번에 읽고 쓸 때에만 주로 사용한다. Variant arry를 이용하여 많은 양의 시트 데이터를 읽고 쓰는 방법에 대해서는 아래 글을 참고한다.

VBA 코딩 패턴: Range Loop-읽기(Read)

VBA 코딩 패턴: Range Loop-쓰기(Write)

Variant 데이터 형식을 사용하는 예제 코드이다. 정수, 문자열, 실수, 날짜 데이터 형식을 모두 처리할 수 있는 것을 보여준다.

Sub VariantTest()
    Dim a As Variant '데이터 형식을 생략하면 Variant 형식임
    a = 1: Debug.Print a
    a = "1": Debug.Print a
    a = 1.1: Debug.Print a
    a = CDate("2021-07-31"): Debug.Print a
End Sub

User-defined(사용자 정의) 데이터 형식

사용자 정의 자료형을 선언하고 사용할 수 있다. C언어의 ‘struct’와 비슷한 ‘Type’ keyword로 사용자 정의 자료형을 선언한다. User-defined 데이터 형식은 개체가 아니라서 선언하면 바로 instance가 생성되어 메모리가 할당되고 값을 입력할 수 있다.

User-defined 데이터 형식에 대한 자세한 내용은 아래 URL을 참고하기 바란다.

https://docs.microsoft.com/en-us/office/vba/language/how-to/user-defined-data-type

User-defined 데이터 형식의 예시 코드는 다음과 같다.

Type EmployeeRecord    ' 사용자 정의 형식을 만듭니다.
    ID As Integer    ' 데이터 형식의 요소를 정의합니다.
    Name As String
    Address As String
    Phone As Long
    HireDate As Date
End Type

Sub CreateRecord()
    Dim MyRecord As EmployeeRecord    ' 변수를 선언합니다.
    MyRecord.ID = 12003    ' 요소에 값을 할당합니다.
    MyRecord.Name = "Andy"
    MyRecord.HireDate = CDate("2021-07-31")
End Sub

3.3.2. 자료구조

자주 사용하는 자료구조는 Array, Collection, Dictionary가 있다. 각각에 대해 살펴보자.

Array

고정 개수의 Item을 가진다. 개체가 아니라서 선언하면 instance가 생성된다. 선언할 때 차원의 수와 각 차원의 하한, 상한 범위를 지정할 수도 있고, 실행시에 동적으로 배열의 차원, 범위를 변경할 수도 있다. 각 차원의 하한과 상한을 지정하지 않고 item의 개수만 지정할 경우 기본적으로 하한은 0이다. Option Base 1을 사용하면 기본 하한은 1이 된다.

선언 예시 코드

Dim DayArray(50)
Dim Matrix(3, 4) As Integer
Dim MyMatrix(1 To 5, 4 To 9, 3 To 5) As Double

각 차원 하한값/상한값 선언, 확인: LBound, UBound 사용

Dim A(1 To 100, 0 To 3, -3 To 4) 
LBound(A, 1) ->  1,  UBound(A, 1) -> 100 ' 1차원 하한/상한
LBound(A, 2) ->  0,  UBound(A, 2) -> 3   ' 2차원 하한/상한
LBound(A, 3) -> -3,  UBound(A, 3) -> 4   ' 3차원 하한/상한

차원 크기 변경: Redim 문으로 동적 배열의 차원 크기를 변경한다.

Dim MyArray() As Integer ' 동적 배열을 선언합니다. 
Redim MyArray(5) ' 5개의 요소를 할당합니다. 
Redim Preserve MyArray(15) ' 15개의 요소로 크기를 변경합니다.

Item Loop(For Next)

'Split & Trim 처리
Public Function SplitTrim(aExpression As String, aDelimeter As String) As String()
    Dim saOut() As String, i As Integer
    saOut = Split(aExpression, aDelimeter)
    For i = LBound(saOut) To UBound(saOut)
        saOut(i) = Trim(saOut(i))
    Next i

    SplitTrim = saOut
End Function

초기화: Erase 문으로 배열 변수를 초기화한다.

' 배열 변수를 선언합니다.
Dim NumArray(10) As Integer    ' 정수 배열입니다.
Dim StrVarArray(10) As String    ' 변수 문자열 배열입니다.
Dim StrFixArray(10) As String * 10    ' 고정 문자열 배열입니다.
Dim VarArray(10) As Variant    ' Variant 배열입니다.
Dim DynamicArray() As Integer    ' 동적 배열입니다.
ReDim DynamicArray(10)    ' 저장 공간을 할당합니다.
Erase NumArray    ' 0으로 지정된 각 요소입니다.
Erase StrVarArray    ' 길이가 0인 문자열 ("")로 지정된 각 요소입니다.    
Erase StrFixArray    ' 0으로 지정된 각 요소입니다.
Erase VarArray    ' Empty로 지정된 각 요소입니다.
Erase DynamicArray    ' 배열에 의해 사용되는 빈 메모리입니다.

Collection

Collection class는 동적 배열(Array)과 유사하다. 가변 갯수의 unique item을 Add, Remove할 수 있다. 개체이기 때문에 “Set” 과 “New”키워드를 이용하여 instance를 생성한다. Visual Basic 언어에서 개체에 reference를 생성하거나 새로운 reference를 할당할 때는 꼭 “Set” keyword를 사용해야 하고, 변수에 값을 할당할 때는 “Set” keyword가 필요없다. 개체를 다룰 때와 변수를 다룰 때를 잘 구분해야 문법 오류가 발생하지 않는다. 자주 실수할 수 있으니 주의가 필요하다.

Collection 개체 선언, instance 생성, Item 추가 등의 작업별 코드는 아래 표를 참고한다.

TaskSample Code
선언Dim oCol As Collection
Instance 생성Set oCol = New Collection
선언과 동시에 Instance 생성Dim oCol As New Collection
Item 추가oCol.Add “Apple”
Index로 Item 접근oCol(1)
Item 개수oCol.Count
Item Loop (For)Dim l As Long
For l = 1 to oCol.Count
    Debug.Print oCol(l)
Next
Item Loop (For Each)Dim fruit As Variant
For Each fruit in oCol
    Debug.Print fruit
Next
Item 제거 (Index 지정)oCol.Remove(1)
Instance 제거Set oCol = Nothing

Collection 을 사용하는 예시 코드는 다음과 같다. 참고로 Collection의 Item은 1부터 시작한다.

Sub CollectionTest()
    Dim oCol As Collection
    Set oCol = New Collection
    
    oCol.Add "Apple"
    oCol.Add "Strawberry"
    oCol.Add "Lemon"
    oCol.Add "Banana"
    
    Debug.Print oCol(1)
    Debug.Print oCol.Item(1)
    Debug.Print "----------"

    Dim l As Long
    For l = 1 To oCol.Count
        Debug.Print oCol(l)
    Next

    Debug.Print "----------"

    oCol.Remove (1)

    Dim fruit As Variant
    For Each fruit In oCol
        Debug.Print fruit
    Next

    Set oCol = Nothing
End Sub

'출력
Apple
Apple
----------
Apple
Strawberry
Lemon
Banana
----------
Strawberry
Lemon
Banana

Dictionary

Key-Value 구조의 가변 unique Item을 관리할 수 있고, item을 동적으로 Add/Remove 할 수 있다.

Python 언어의 Dictionary, C++의 HashMap, Java의 HashMap과 유사한 자료구조이다. Key값으로 접근할 때 성능은 O(1) 수준이다.

Dictionary class는 기본으로 제공되지 않는다. Early binding 방식으로 사용하려면 먼저 “Microsoft Scripting Runtime”을 참조해야 한다. Late binding 방식으로 사용하려면 CreateObject를 통해 instance를 생성하고 사용한다.

Dictionary class 사용을 위한 "Microsoft Scripting Runtime" 참조 추가
Dictionary class 사용을 위한 “Microsoft Scripting Runtime” 참조 추가

Dictionary 개체 선언, instance 생성, Item 추가 등의 작업별 코드는 아래 표를 참고한다.

TaskSample Code
선언 (early binding)Dim oDic As Dictionary
Instance 생성 (early binding)Set oDic = New Dictionary
선언 (late binding)Dim oDic As Object
Instance 생성 (late binding)Set oDic = CreateObject(“Scripting.Dictionary”)
Item 추가oDic.Add “Apples”, 50
Value 변경oDic(“Apples”) = 60
Value 얻기appleCount = oDic(“Apples”)
Key가 존재하는지 확인oDic.Exists(“Apples”)
Item 삭제oDic.Remove(“Apples”)
모든 Item 삭제oDic.RemoveAll
Item 개수oDic.Count
Item Loop (For Each)Dim key As Variant
For Each key in oDic.Keys
    Debug.Print key, oDic(key)
Next key
Item Loop (For, Early binding only)Dim l As Long
For l = 0 To oDic.Count -1
    Debug.Print oDic.Keys(l), oDic.Items(l)
Next l

Dictionary를 사용하는 예시 코드는 다음과 같다. 참고로 Dictionary의 Items는 0부터 시작한다.

Sub DictionaryTest()
    Dim oDic As Dictionary
    Set oDic = New Dictionary

    oDic.Add "A", "Apple"
    oDic.Add "S", "Strawberry"
    oDic.Add "L", "Lemon"
    oDic.Add "B", "Banana"

    Debug.Print oDic("A")
    Debug.Print oDic.Items(0)
    Debug.Print "----------"

    Dim l As Long
    For l = 0 To oDic.Count - 1
        Debug.Print oDic.Items(l)
    Next
    
    Debug.Print "----------"
    
    oDic.Remove ("A")

    Dim key As Variant, fruit As String
    For Each key In oDic.Keys
        fruit = oDic(key)
        Debug.Print fruit
    Next

    Set oDic = Nothing
End Sub

'출력
Apple
Apple
----------
Apple
Strawberry
Lemon
Banana
----------
Strawberry
Lemon
Banana

Dictionary 개체를 For Loop 구문으로 탐색할 때 key값을 담을 변수는 Variant 또는 Object 형식만 가능하다. 위 예시에서 23, 24 행의 코드에서는 Variant 형식을 사용했다.


이번 글에서는 VBA 데이터 형식과 자료구조에 대해 살펴보았다. 특히 Collection과 Dictionary는 자주 사용할 가능성이 매우 높기 때문에, 잘 익혀 두기 바란다. 다음에는 VBA 코딩시 알아두면 좋은 How-To에 대해 살펴보겠다.


<< 관련 글 목록 >>

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

ko_KR한국어