VBAクラスのAttributeについて(既定メンバーとFor Each)
VBAクラスをエクスポートすると各種のAttributeが設定されているのが確認できます。
それぞれのAttributeの意味と、さらに追加で指定できるAttributeについて説明します。
どのようなものがあるかを知るのは、VBAの深部を知るうえでも役に立つと思います。
全てのAttributeが使えるわけではなく、VBAとしての制限があります。
このページは少々見づらく、また自動翻訳のため意味も分かりづらくなっています。
自身の覚え書きの意味も含めて、再検証しつつ制限等を追加解説したものになります。
基本的なVBAコードは、上記ページのコードを使っています。
VBAクラスのエクスポートとインポート
・クラスをエクスポート(.cls)
・(.cls)をテキストエディタで編集
・(.cls)をインポート
これにより指定したAttributeがVBAで有効となります。
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "Class1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
・・・以下、通常のクラスコード・・・
上記のうち、以下はVBAでは指定が無効か変更しないものになります。
MultiUse = -1 ・・・ VBAでは無効
Attribute VB_Name = "Class1" ・・・ クラス名なので変更しない
Attribute VB_GlobalNameSpace = False ・・・ VBAでは無効
Attribute VB_Creatable = False ・・・ VBAでは無効
Attribute VB_PredeclaredId
Attribute VB_Exposed
さらに、追加可能なAttributeとして、
Attribute procName.VB_Description
Attribute variableName.VB_VarUserMemId
Attribute procName.VB_UserMemId
以上について説明します。
Attribute VB_PredeclaredId
既定はFalseとなっています。
Trueを指定することで、
クラスのグローバルデフォルトインスタンスが作成されます。
デフォルトのインスタンスは、クラスの名前を介してアクセスされます。
Newキーワードでインスタンスを作成することなく、直接クラス名が使えるようになります。
Dim cls As New Class1
Debug.Print cls.item
Attribute VB_PredeclaredId = True
.clsにこのAttributeを指定しインポートしたクラスは、グローバルインスタンスが作成されます。
したがって、インスタンスを作成することなくクラスを使用できるようになります。
Debug.Print class.item
Attribute VB_Exposed
既定はFalseとなっています。
クラスのインスタンス化特性を制御します。
クラスのプロパティInstancingと連動しています。
PublicNotCreatable → Attribute VB_Exposed = True
ただし、VBAではVB_Createableが無視されるため、
クラスのインスタンスを外部から直接作成することはできません。
Attribute [procName.]VB_Description
オブジェクトエクスプローラで表示されるクラスにテキストの説明を追加します。
Attribute VB_Name = "Class1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Attribute VB_Description = "VBAクラスの説明"
オブジェクトエクスプローラで表示されるクラスのメンバーにテキストの説明を追加します。
Public Property Get item(ByVal index As Long) As Variant
Attribute Item.VB_Description = "クラスの既定のメンバー"
Attribute Item.VB_UserMemId = 0
item = internal(index)
End Property
このItemは特にメンバー名と一致している必要はありませんが、通常は一致させておいたほうが良いでしょう。
Attribute Item.VB_Description
この挿入位置は、当該プロシージャー/プロパティの中(直後からEndの前)であればどこでも構いません。
プロパティではすべてのアクセサメンバー(Get、Let、Set)は同じ説明を使用します。
したがって、どのアクセサに指定しても構いません。
Attribute variableName.VB_VarUserMemId
モジュールスコープ変数をクラスのデフォルトメンバーに指定します。
・変数宣言の直後に指定
・variableNameは変数名と一致させる
・モジュールレベルのPublic変数
以上の条件を満たしてください。
(この制限の一部は実際にやってみた上での制限で、ドキュメントに見当たらないものもあります。)
Public count As Long
Attribute count.VB_VarUserMemId = 0
Private Sub Class_Initialize()
count = 123
End Sub
標準モジュールではクラスのインスタンスだけ指定したときcountプロパティが既定となります。
Dim cls As New Class1
Debug.Print cls
clsだけの記述で、cls.countが既定メンバーとして動作します。
イミディエイトには「123」と出力されます。
Attribute procName.VB_UserMemId = 0
クラスのデフォルトメンバーに指定します。
この挿入位置は、当該プロシージャー/プロパティの中(直後からEndの前)であればどこでも構いません。
procNameの文字列は特に使われていませんので、
プロシージャー/プロパティ名と一致している必要はありませんが、通常は一致させておいたほうが良いでしょう。
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "Class1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Attribute VB_Description = "VBAクラスの説明"
Option Explicit
Private internal As New Collection
Public Property Get item(ByVal index As Long) As Variant
Attribute item.VB_Description = "クラスの既定のメンバー"
Attribute item.VB_UserMemId = 0
item = internal(index)
End Property
Public Property Set item(ByVal index As Long, ByVal value As Variant)
With internal
If index = .count + 1 Then
.Add item:=value
ElseIf index = .count Then
.Remove index
.Add item:=value
ElseIf index < .count Then
.Remove index
.Add item:=value, before:=index
End If
End With
End Property
標準モジュールではクラスのインスタンス変数だけを指定したときItemプロパティが既定となります。
Sub test()
Dim cls As New Class1
Set cls(1) = Range("A1")
Set cls(2) = Range("A2")
Debug.Print cls(2).Address
End Sub
cls(n)は、cls.Item(n)になります。
イミディエイトには"$A$2"と出力されます。
Attribute procName.VB_UserMemId = -4
For Eachループ構造でクラスを反復可能にします
このメンバーが列挙子を生成することをVBAに伝えます。
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "Class1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Attribute VB_Description = "VBAクラスの説明"
Option Explicit
Private internal As New Collection
Public Property Get item(ByVal index As Long) As Variant
Attribute item.VB_Description = "クラスの既定のメンバー"
Attribute item.VB_UserMemId = 0
item = internal(index)
End Property
Public Property Let item(ByVal index As Long, ByVal value As Variant)
With internal
If index = .count + 1 Then
.Add item:=value
ElseIf index = .count Then
.Remove index
.Add item:=value
ElseIf index < .count Then
.Remove index
.Add item:=value, before:=index
End If
End With
End Property
Public Property Get NewEnum() As IUnknown
Attribute NewEnum.VB_Description = "リストを反復処理する列挙子を取得します。"
Attribute NewEnum.VB_UserMemId = -4
Set NewEnum = internal.[_NewEnum]
End Property
ここでは、Itemに、
Attribute item.VB_UserMemId = 0
これを指定しています。
そして、
Public Property Get NewEnum() As IUnknown
これを定義します。
Collectionの非表示メンバー[_NewEnum]を使っています。
_NewEnumは_記号から始まるメンバーなので[ ]で囲みます。
Sub test()
Dim cls As New Class1
Dim rng As Range, ix As Long
ix = 1
For Each rng In Range("A1:B5")
Set cls(ix) = rng
ix = ix + 1
Next
For Each rng In cls
Debug.Print rng.Address
Next
End Sub
イミディエイトには、
$A$1
$B$1
$A$2
・・・
と出力されます。
ステップインで実行すると、For Eachの時点でNewEnumが動いているのが分かります。
VBAクラスのAttributeの最後に
実務において、このような技術を使う事はほとんどありませんが、
もし必要になったら、いつでも使えるように用意しておこうという事です。
VBの時から裏技的なものとなっていましたので、さすがにVBAで使う事に対する良し悪しはあるようにも思います。
ですが、実際にVBAではずっと使えているものでもあるので、今後もサポートされ続けるものと思われます。
もしもの時には、ここを見ればいつでも実装できるように準備しておいたということです。
同じテーマ「VBAクラス入門」の記事
VBAクラスの作り方:列名のプロパティを自動作成する
VBAクラスの作り方:独自Rangeっぽいものを作ってみた
クラスとイベントとマルチプロセス並列処理
クラスとCallByNameとポリモーフィズム(多態性)
オートフィルターを退避回復するVBAクラス
オートフィルター退避回復クラスを複数シート対応させるVBAクラス
コレクション(Collection)の並べ替え(Sort)に対応するクラス
VBAクラスのAttributeについて(既定メンバーとFor Each)
VBAクラスを使ったイベント作成(Event,RaiseEvent,WithEvents)
VBAで音楽再生するクラスを作成
図形を方程式で動かすVBAクラス
新着記事NEW ・・・新着記事一覧を見る
TRIMRANGE関数(セル範囲をトリム:端の空白セルを除外)|エクセル入門(2024-08-30)
正規表現関数(REGEXTEST,REGEXREPLACE,REGEXEXTRACT)|エクセル入門(2024-07-02)
エクセルが起動しない、Excelが立ち上がらない|エクセル雑感(2024-04-11)
ブール型(Boolean)のis変数・フラグについて|VBA技術解説(2024-04-05)
テキストの内容によって図形を削除する|VBA技術解説(2024-04-02)
ExcelマクロVBA入門目次|エクセルの神髄(2024-03-20)
VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
アクセスランキング ・・・ ランキング一覧を見る
1.最終行の取得(End,Rows.Count)|VBA入門
2.繰り返し処理(For Next)|VBA入門
3.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
4.変数宣言のDimとデータ型|VBA入門
5.RangeとCellsの使い方|VBA入門
6.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
7.セルのクリア(Clear,ClearContents)|VBA入門
8.メッセージボックス(MsgBox関数)|VBA入門
9.条件分岐(Select Case)|VBA入門
10.ブック・シートの選択(Select,Activate)|VBA入門
このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。