見出し画像

VBAのEnumの「メンバーの名前」をデータとして取得する方法

 VBAには列挙型Enumという数値を定義するものがあります。プログラム中で整数値で「3」などと数字をそのまま使うと何のことかわからなくなったりしますし、後で修正するときにもとても不都合です。Enumはそういうのを避けるために、何かの番号とかをあらかじめ名前に割り当てて定義しておきます。
 こんな感じです。

Private Enum testE
  No = 0
  Name
  Address
  Item
End Enum

 こうすると、testE.Noは実行時に0が割り当てられます。testE.Nameなら1です。

 通常は、こうやって使えばそれでよいだけなのですが、どうしても、どうしても、このEnumの定義文字そのものをプログラム中で欲しいという時があります。でも普通は、VBAではそれはできません。(C#だとできます。)

 普通はできないし、しないのですが、VBEを操作するVBProjectというオブジェクトにVBAのソースコードそのものを取得する仕組みがありますので、それを使って簡単なコードを書けば可能になります。

 今、以下のような列挙型の定義があるとします。

Private Enum testEnum
    'アジア
    Japan = 5
    '北米
    Americ = 7
    'ヨーロッパ
    England = 10
    France 'フランス
    Spain 'スペイン
    '南米
    Brasil = 20
    Chili
End Enum

 作成したコードを使うと

Japan          5 
Americ         7 
England        10 
France         11 
Spain          12 
Brasil         20 
Chili          21 

という文字列と数値が取得できます。

 取得のためのソースコードは以下です。詳しい説明は省きます。よくわからないままにやるとひどい目に合う(VBA作成中にExcelがフリーズしたり、再起動して作成したものが消えてしまう)ことがあるので、VBEを操作する内容のほかの人のWEB記事を、あらかじめお調べください。すいません。
 

Public Sub testGetEnumMember()
  Const ModName = "Module1" '取得するモジュールの名前
  Const WordS = "Private Enum testEnum" '対象のEnumの開始文字
  Const WordE = "End Enum" '対象のEnumの終了文字

  Dim member As Dictionary
  Set member = GetEnumMember(ModName, WordS, WordE)

  '結果の表示。
  Dim keywd As Variant
  For Each keywd In member.Keys
    Debug.Print keywd, member(keywd)
  Next
End Sub
Private Function GetEnumMember(ModName As String, WordS As String, WordE As String) As Dictionary
'参照設定で
'「Microsoft Visual Basic for Applications Extensibility 5.3」
'を追加した方が良い。

'宣言部分を取得
Dim VBCs As VBComponents 'VBコンポーネンツ。VBA全体のオブジェクト
Set VBCs = ThisWorkbook.VBProject.VBComponents
Dim VBC As VBComponent 'VBコンポーネント。標準モジュールなどのオブジェクト
Set VBC = VBCs(ModName)
Dim CM As CodeModule 'コードモジュール。ソースコードのオブジェクト
Set CM = VBC.CodeModule

Dim decline As Long
decline = CM.CountOfDeclarationLines 'グローバル宣言部の行数。
Dim buff As Variant
buff = Split(CM.Lines(1, decline), vbCrLf) 'グローバル宣言部を取得して、行に分割
Set CM = Nothing
Set VBC = Nothing
Set VBCs = Nothing

Dim member As New Dictionary 'Enumのメンバーを保存する辞書
Dim cnt As Long 'Enumの値
cnt = 0
Dim flg As Boolean '必要範囲になったことを示すスイッチ
flg = False
Dim pos As Long 'コメント除去、値取得時に使う文字数カウント
Dim str As String, preEQ As String, postEQ As String 'コメント除去、値取得時に使う文字変数
Dim i As Long
For i = 0 To UBound(buff) '宣言部を1行ずつ調べる
    str = buff(i)
    
    '終了かチェックする
    If flg And InStr(1, str, WordE) > 0 Then
        Exit For
    End If
    
    '対象のEnumの行
    If flg Then
        preEQ = ""
        postEQ = ""
        'コメント除去
        pos = InStr(1, str, "'")
        If pos > 0 Then
            str = Left(str, pos - 1)
        End If
        If Trim(str) <> "" Then '空行は飛ばす
            '値取得
            pos = InStr(1, str, "=")
            If pos > 0 Then
                preEQ = Trim(Left(str, pos - 1))
                postEQ = Mid(str, pos + 1)
                cnt = CLng(postEQ)
            Else
                preEQ = Trim(str)
                cnt = cnt + 1
            End If
            '辞書に登録
            member(preEQ) = cnt
        End If
    End If
    
    '対象のEnumに入ったかチェックする
    If InStr(1, str, WordS) > 0 Then
        flg = True
    End If
Next

Set GetEnumMember = member
Set member = Nothing
End Function

#Excel ,#VBA,#VBE, #VBComponents ,#CodeModule


応援してやろうということで、お気持ちをいただければ嬉しいです。もっと勉強したり、調べたりする糧にしたいと思います。