複数のデータ型をまとめるユーザー定義型


ユーザー定義型は、C言語でいう構造体のような仕組みです。

一般的な変数には、1つの値しか格納できません。配列には複数の値を同時に格納できますが、それは同じ型の値です。名前(文字列型)と年齢(長整数型)のように、異なる型の値をセットにして格納するには、配列ではなくユーザー定義型が便利です。ユーザー定義型は、次のようにして使います。

Type ○○
    要素1 As 型
    要素2 As 型
End Type
Sub Sample()
    Dim 変数名 As ○○
    変数名.要素1 = 値
    変数名.要素2 = 値
End Sub

ユーザー定義型の定義は、宣言セクションでします。宣言セクションとは、モジュールの一番上に記述したプロシージャの、さらに上の部分です。変数の宣言を強制するオプションを設定したとき、モジュールに挿入されるOption Explicitや、APIの宣言やパブリック変数の宣言などをするのと同じ場所です。

ユーザー定義型として定義した型を変数として使うには、そのほかの型宣言と同じように「Dim 変数名 As ○○」と指定します。As まで入力すると、ユーザー定義型として定義した型名がリストに表示されます。

Type Personal
    Name As String
    Age As Long
End Type
Sub Sample56()
    Dim Member As Personal
    Member.Name = "tanaka"
    Member.Age = 38
End Sub

ちょっと複雑になりますが、ユーザー定義型で定義する要素の型に、別のユーザー定義型を指定することも可能です。

Type Personal
    Name As String
    Age As Long
End Type
Type Area
    Tokyo As Personal
    Yokohama As Personal
End Type
Sub Sample57()
    Dim Member As Area
    Member.Tokyo.Name = "suzuki"
    Member.Yokohama.Age = 28
End Sub

複数の値をセットにして管理するとはいえ、その数が少ないときは一般的な変数でも代用できます。上記の例は、次のように書いても大きな違いはありません。

Sub Sample58()
    Dim UserName As String, UserAge As Long
    UserName = "tanaka"
    UserAge = 38
End Sub

ユーザー定義型が活躍するのは、そうしたセットのデータを大量に管理する場合でしょう。そんなときは、ユーザー定義型の配列を使います。たとえば、次のようなCSVデータがあったとします。

ワークシート上に入力されているデータなら、何も変数に格納しなくたって、セルを検索すれば事が足ります。セルに入力されているということは、変数に格納されているようなものですから。そうではなく、CSVデータのように外部ファイルとしてデータが存在する場合は、一度変数に格納しておくと後々の処理が楽になります。ここでは、UserFormと組み合わせた例をお見せします。ちょっと長いですけど、実用的なマクロとなると、どうしてもこれくらいになっちゃいますね。がんばって読んでください。

Private Type Personal
    Name As String
    Age As Long
    Area As String
    Sex As String
End Type
Dim Member() As Personal
Private Sub ListBox1_Change()
    Dim i As Long
    For i = 0 To UBound(Member)
        If Member(i).Name = ListBox1.Value Then
            Label1.Caption = Member(i).Age
            Label2.Caption = Member(i).Area
            If Member(i).Sex = "男性" Then
                OptionButton1.Value = True
            Else
                OptionButton2.Value = True
            End If
            Exit Sub
        End If
    Next i
End Sub
Private Sub UserForm_Initialize()
    Dim buf As String, i As Long
    Const Data As String = "C:\Work\Member.csv"
    If Dir(Data) = "" Then Exit Sub
    Open Data For Input As #1
        Do Until EOF(1)
            Line Input #1, buf
            ReDim Preserve Member(i)
            Member(i).Name = Split(buf, ",")(0)
            Member(i).Age = Split(buf, ",")(1)
            Member(i).Area = Split(buf, ",")(2)
            Member(i).Sex = Split(buf, ",")(3)
            i = i + 1
        Loop
    Close #1
    For i = 0 To UBound(Member)
        ListBox1.AddItem Member(i).Name
    Next i
    ListBox1.ListIndex = 0
End Sub