シートモジュールとインターフェイス

シートモジュールにインターフェイスを実装する

単なる実験。

インターフェイスを作成する

クラスモジュールを挿入して、次のコードを書く。

オブジェクト名はIA1ValueShowableとする。

ちなみに、Instancingプロパティの値を「PublicNotCreatable」にしています。

リスト1 クラスモジュール
Option Explicit

Public Sub showA1Value()
End Sub

たったこれだけ。showA1Valueというメソッドだけを定義しておく。

これで、このインターフェイスImplementsしたオブジェクトには、必ずshowA1Valueというメソッドを持たせなくてはならないことになる。

シートモジュールにインターフェイスを実装する

今回は、Sheet6モジュールとSheet7モジュールの2つにインターフェイスIA1ValueShowable」を実装する。

スト2 Sheet6モジュール
Option Explicit

Implements IA1ValueShowable

Public Sub IA1ValueShowable_showA1Value()
  Call makeUserSick(Me.Range("A1").Value)
End Sub

Sheet6モジュールのshowA1Valueメソッドでは、当ブログではおなじみのmakeUserSickメソッドを使用してA1セルの値を表示する。

makeUserSickメソッドについては、コチラをどうぞ。

リスト3 Sheet7モジュール
Option Explicit

Implements IA1ValueShowable

Public Property Get BASE_CELL() As Range
  Set BASE_CELL = Me.Range("A1")
End Property

Public Sub IA1ValueShowable_showA1Value()
  Call MsgBox(Me.Range("A1").Value)
End Sub

Propertyのところは前回の名残。

Sheet7モジュールのshowA1Valueメソッドでは、単なるMsgBoxを使う。

これで準備完了。

使ってみる

標準モジュールに次のコードを書いて実行してみる。

リスト4 標準モジュール
Public Sub testInterfaceSheetModule()
  Dim Sh(1) As IA1ValueShowable    '……(1)'
  Set Sh(0) = Sheet6    '……(2)'
  Set Sh(1) = Sheet7
  Dim i As Long
  For i = 0 To 1    '……(3)'
    Call Sh(i).showA1Value
  Next
End Sub

まず、(1)の

Dim Sh(1) As IA1ValueShowable

で、インターフェイスIA1ValueShowable型の配列Shを準備。

(2)からの2行

Set Sh(0) = Sheet6
Set Sh(1) = Sheet7

Sheet6Sheet7を配列Shにぶち込む。

後は(3)からの3行

For i = 0 To 1
  Call Sh(i).showA1Value
Next

Forループを用いてshowA1Valueメソッドを実行する。

実行結果

f:id:akashi_keirin:20180831203332j:plain

f:id:akashi_keirin:20180831203339j:plain

このように、同じshowA1Valueメソッドを呼び出すことでそれぞれ異なる動作をさせることができた。

おわりに

Subだとこのようにうまくいったのだが、Range型のPropertyだとうまくいかなかった。なぜだろう。

追記

Propertyの識別子をBase_Cellとしていたのだが、どうも「_」(アンダースコア)がまずかった模様。クラスモジュールIA1ValueShowable内で

Public Property Get Base_Cell() As Range

End Property

このように定義し、これに合わせてSheet6Sheet7モジュールのそれぞれにBase_Cellプロパティを設定したところ、

f:id:akashi_keirin:20180831210612j:plain

こんなエラーが出てどうしようもなかったのだが、識別子から「_」を取り除いて次のようなコードにすると上手くいったので、全てのコードを載っけておく。

リスト5 クラスモジュール
'オブジェクト名:IA1ValueShowable'
Option Explicit

Public Property Get Name() As String

End Property

Public Property Get BaseCell() As Range

End Property

Public Sub showA1Value()
End Sub
リスト6 Sheet6モジュール
Option Explicit

Implements IA1ValueShowable

Public Property Get IA1ValueShowable_Name() As String
  IA1ValueShowable_Name = "Sheet6"
End Property

Public Property Get IA1ValueShowable_BaseCell() As Range
  Set IA1ValueShowable_BaseCell = Me.Range("A1")
End Property

Public Sub IA1ValueShowable_showA1Value()
  Call makeUserSick(Me.Range("A1").Value)
End Sub
リスト7 Sheet7モジュール
Option Explicit

Implements IA1ValueShowable

Public Property Get IA1ValueShowable_Name() As String
  IA1ValueShowable_Name = "Sheet7"
End Property

Public Property Get IA1ValueShowable_BaseCell() As Range
  Set IA1ValueShowable_BaseCell = Me.Range("A1")
End Property

Public Sub IA1ValueShowable_showA1Value()
  Call MsgBox(Me.Range("A1").Value)
End Sub
リスト8 標準モジュール
Public Sub testInterfaceSheetModule()
  Dim Sh(1) As IA1ValueShowable
  Set Sh(0) = Sheet6
  Set Sh(1) = Sheet7
  Dim i As Long
  For i = 0 To 1
    Call Sh(i).showA1Value
    Debug.Print Sh(i).Name
    Debug.Print Sh(i).BaseCell.Value
  Next
End Sub

リスト8を実行すると、リスト4実行時同様2つのメッセージが出た後、イミディエイトに

f:id:akashi_keirin:20180831210619j:plain

このように表示される。

VBAインターフェイスを使う場合、どうも「_」(アンダースコア)が特別な意味を持っているらしい。気をつけねば。

追記

面白半分にシートモジュールにインターフェイスを実装すると、えらいことになります。

akashi-keirin.hatenablog.com

akashi-keirin.hatenablog.com