構造体とは、複数のデータを一つのかたまりにまとめて扱ったものです。VBAではユーザー定義型と呼ばれる独自のデータ型を定義することができる便利な機能の1つです。構造体を使うことで、データベースなどでの大規模なデータの取り扱いがより簡単に行えるようになります。
Excel VBAの構造体とは
構造体とは、複数のデータを1つのかたまりにまとめたものです。複数のデータを1つにまとめるには他にも配列などがありますが、構造体は配列とは異なり、順番に左右されずにデータを呼び出すことができます。
構造体の使い方
さっそく、VBAでの構造体の使い方について説明していきます。
まずは構造体の定義を宣言して、値を初期化するところから解説します。
構造体を宣言する
構造体はVBAではユーザー定義型というデータ型のことを指しています。たとえば変数を宣言する時の As String や As Range といった部分の As の後ろに来るものがデータ型です。
Type ステートメントを使用することで、ユーザー定義型を宣言することができます。
【基本構文】
Type データ型名
要素名1 As データ型
要素名2 As データ型
...
End Type
まず、Type ステートメントのあとに使用したいデータ型名を定義します。ここで定義した名前が、データ型として扱われるようになります。
次に、要素名を定義します。要素は一般的なオブジェクトにとってのプロパティと同じようなものです。全ての要素でデータ型が一致している必要はなく、要素ごとに異なる型のデータを格納できます。
必要な要素を全て宣言したら End Type ステートメントで構造体を閉じます。
実際に、 userInfo というデータ型を宣言してみます。
【サンプルコード】
Type userInfo
name As String
id As Integer
address As String
age As Integer
End Type
ユーザー定義型を宣言する際の注意点
ユーザー定義型はモジュールレベルでのみ使用できます。そのため、上のサンプルコードのように構造体を宣言するには、VBAのオブジェクト構造のうち、シートではなくモジュールという場所で宣言する必要があります。
Type ステートメントをシート内の処理で宣言しようとすると、下のようにエラーになります。
【エラー結果】
構造体にデータを格納する
先ほど宣言した構造体を実際に使用するために、オブジェクトを定義してデータを格納していく方法について説明します。
まずは、一般的な変数の宣言と同じように Dim オブジェクト名 As データ型名 としてオブジェクトを生成します。
次に、オブジェクトのプロパティに値を代入するときと同様に オブジェクト名.要素名 = 値 とします。
先ほどのサンプルコードで定義した構造体を使用して、実際にデータを格納してみましょう。
【サンプルコード】
'標準モジュールなどで宣言してください
Type userInfo
name As String
id As Integer
address As String
age As Integer
End Type
'userInfoを初期化します
Sub callUserInfo()
Dim user1 As userInfo
user1.name = "Yamada"
user1.id = 1
user1.address = "Tokyo"
user1.age = 30
'メッセージボックスに各要素の値を表示
MsgBox "ID: " & user1.id & vbCrLf & "名前: " & user1.name & vbCrLf & "住所: " & user1.address & vbCrLf & "年齢: " & user1.age
End Sub
【実行結果】
このサンプルコードでは、最初に作成した userInfo というデータ型で user1 というオブジェクトを生成しています。
そして、オブジェクト user1 の各要素を呼び出して値を代入することで、オブジェクトを初期化しています。
なお、ユーザー定義型を作成する Type ステートメントは必ずそのオブジェクトを生成する Sub プロシージャの外(Sub () … End Sub に挟まれていない場所)に記述しましょう。
構造体を関数の引数に指定する
Function プロシージャの引数に構造体を指定すると、使用する引数の数を減らせます。
気を付けるべき点として、構造体はオブジェクトなので、 Function プロシージャの引数で渡す際は参照渡しを行う必要があります。
参照渡しで引数を渡すには、 ByRef ステートメントを記述します。
実際のコードで確認してみましょう。
【サンプルコード】
'ユーザー定義型の宣言は省略
Sub callUserInfo2()
Dim user1 As userInfo
user1.name = "Yamada"
user1.id = 1
user1.address = "Tokyo"
user1.age = 30
'下の Function の処理が走る
dataView user1
End Sub
Function dataView(ByRef p As userInfo)
MsgBox "ID: " & p.id & vbCrLf & "名前: " & p.name & vbCrLf & "住所: " & p.address & vbCrLf & "年齢: " & p.age
End Function
実行結果については、先ほどの例と全く同じ結果になるので省略します。
ここでは、 Function プロシージャの処理を Sub プロシージャの中で実行しています。
引数に構造体を指定したことで、引数が何個も必要になるはずの処理を一つの引数で済ませることができました。
配列の中に構造体を格納する
構造体は配列に格納することができます。
構造体を配列の要素として格納することで、同じユーザー定義型の複数の構造体をまとめることができます。
【サンプルコード】
Sub callUsersInfo()
Dim users(3) As userInfo
users(0).name = "Yamada"
users(0).id = 1
users(0).address = "Tokyo"
users(0).age = 30
users(1).name = "Tanaka"
users(1).id = 2
users(1).address = "Nagoya"
users(1).age = 29
users(2).name = "Satou"
users(2).id = 5
users(2).address = "Sendai"
users(2).age = 41
Dim i As Integer
For i = LBound(users) To UBound(users) - 1
dataView users(i)
Next i
End Sub
Function dataView(ByRef p As userInfo)
MsgBox "ID: " & p.id & vbCrLf & "名前: " & p.name & vbCrLf & "住所: " & p.address & vbCrLf & "年齢: " & p.age
End Function
【実行結果】
顧客情報などのような、データの種類が決まっていて大量の情報を扱いたいときは構造体と配列などのデータ構造とを組み合わせることで、効率的にデータを処理することができるようになります。
構造体のオブジェクトをコピーする
構造体のオブジェクトは、「=」で他のオブジェクトに代入することで、そのオブジェクトにコピーすることができます。
構造体をコピーする場合は、コピー元とコピー先のオブジェクトが同一のユーザー定義型である必要があるので気を付けましょう。
【サンプルコード】
Sub UsersInfoCopy()
Dim user As userInfo
user.name = "Yamada"
user.id = 1
user.address = "Tokyo"
user.age = 30
Dim userCopy As userInfo
userCopy = user
dataView userCopy
End Sub
Function dataView(ByRef p As userInfo)
MsgBox "ID: " & p.id & vbCrLf & "名前: " & p.name & vbCrLf & "住所: " & p.address & vbCrLf & "年齢: " & p.age
End Function
構造体に構造体をネストする(入れ子にして格納する)
構造体の要素の中に別の構造体を定義することも可能です。
その場合、内側の構造体を先に宣言しておきましょう。
【サンプルコード】
'内側の構造体
Type InnerStruct
Field1 As String
Field2 As String
End Type
'外側の構造体
Type OuterStruct
OuterField As Integer
Inner As InnerStruct
End Type
構造体を扱うコードを書くときの注意点
構造体は複数のデータをまとめて扱うデータであるため、通常の文字列や数値などのデータ型にはできない高度な機能と同時に、構造体では行うことができない機能的な制限などもあります。
ここでは、そのうちのいくつかを解説していきます。
プロシージャの中では宣言できない
最初のほうでも説明しましたが、構造体(ユーザー定義型)は Sub プロシージャの中で宣言することはできません。
このほかにも、 Function プロシージャでも同様です。 Type ステートメントは必ずプロシージャの外のモジュールで宣言するように注意してください。
構造体を関数に渡す際は参照渡しをする
Function プロシージャの引数として構造体を指定するときは、必ず ByRef ステートメントで参照型として渡しましょう。
ByVar ステートメントを使用して値型として渡した場合、その構造体の全体をコピーすることになり、パフォーマンスに悪影響を与えてしまいます。
入れ子にするときは内側の構造体から宣言する
構造体は入れ子にすることができますが、必ず内側の構造体から先に宣言する必要があります。
外側の構造体を先に宣言した場合は、「定義前のユーザー定義型を参照しています」というエラーが出ます。
まとめ
ここまで、VBAの構造体(ユーザー定義型)について解説してきました。
構造体を使うことで、様々なデータ構造を柔軟に扱うことができます。
高機能な代わりに注意すべき点も多いですが、使いこなせれば大規模なデータの処理なども効率的に行えるようになります。
この記事で基礎をおさえて、構造体を使いこなしましょう!
関連記事
VBAの勉強方法は?
書籍やインターネットで学習する方法があります。昨今では、YouTubeなどの動画サイトやエンジニアのコミュニティサイトなども充実していて多くの情報が手に入ります。
そして、より効率的に知識・スキルを習得するには、知識をつけながら実際に手を動かしてみるなど、インプットとアウトプットを繰り返していくことが重要です。特に独学の場合は、有識者に質問ができたりフィードバックをもらえるような環境があると、理解度が深まるでしょう。
ただ、VBAに限らず、ITスキルを身につける際、どうしても課題にぶつかってしまうことはありますよね。特に独学だと、わからない部分をプロに質問できる機会を確保しにくく、モチベーションが続きにくいという側面があります。独学でモチベーションを維持する自信がない人にはプログラミングスクールという手もあります。費用は掛かりますが、その分スキルを身につけやすいです。しっかりと知識・スキルを習得して実践に活かしたいという人はプログラミングスクールがおすすめです。
プログラミングスクールならテックマニアがおすすめ!
ITスキル需要の高まりとともにプログラミングスクールも増えました。しかし、どのスクールに通うべきか迷ってしまう人もいるでしょう。そんな方にはテックマニアをおすすめします!これまで多くのITエンジニアを育成・輩出してきたテックマニアでもプログラミングスクールを開講しています。
<テックマニアの特徴>
・たしかな育成実績と親身な教育 ~セカンドキャリアを全力支援~
・講師が現役エンジニア ~“本当”の開発ノウハウを直に学べる~
・専属講師が学習を徹底サポート ~「わからない」を徹底解決~
・実務ベースでスキルを習得 ~実践的な凝縮カリキュラム~
このような特徴を持つテックマニアはITエンジニアのスタートラインとして最適です。
話を聞きたい・詳しく知りたいという方はこちらからお気軽にお問い合わせください。