メソッドチェーンが使える String クラスを作る
経緯
VBAのショボい点として、String 型でメソッドチェーンが使えない点がある。
メソッドチェーンというのは xxx.Trim.SubString(0,1) のようにメソッドを続けて使える機能。
メソッドチェーンにするためには、クラスを返却するメソッドを作ればいいが、String型も同時に返したい。そんな不可能?と思われたが、試行錯誤してみたところ、実用になるレベルになったのでやりかたを紹介する。
使い勝手は以下のようになる。メソッドをいくらでもつなげて使えるし、メソッドの戻り値をString型と同等の動作 にすることができる。
Sub StringEx_Sample()
Dim s As IString
Set s = New StringEx
'普通にStringっぽく使える
s = "abcdefg "
Debug.Print s
Debug.Print s & "desu"
'Java/C# のようなメソッドチェーンも使える
Debug.Print s.SubString(2, 4)
Debug.Print s.SubString(2, 4).Length
Debug.Print s.Length
Debug.Print s.Trim.Length
End Sub
-----------------------
abcdefg
abcdefg desu
cd
2
9
7
ソース解説
やること。
・String 型を返すメソッドは IString インタフェースを返すようにする。
→これでメソッドチェーンを実現する。
・IString インタフェースにString型の規定のプロパティを作り、メソッドを省略した場合、String 型を返すようにする。
→クラスでありながら、String 型としても扱えるようになる。
IString インターフェース
インターフェースを使用しなくても作れるけど、好きなので。
文字列を保持するためのプロパティ「Value」を定義する。
Value プロパティを規定のプロパティにすると、省略可能になります。
規定のプロパティを作成するためには以下の手順が必要となります。
- クラスをエクスポートする。
- エディタ等でクラスを編集し、プロパティプロシージャ(LetやGetのどちらか1つ)の中に「Attribute Item.VB_UserMemId = 0」を追加する。
- VBEでインポートしなおす。
これはインターフェース側に指定しておけば、Impliments した方でも有効になる。
インターフェースを使用しない場合は、StringEx 側の Value プロパティに上記の設定を行ってください。
Option Explicit
Public Function SubString(ByVal starts As Long, Optional ByVal ends As Long = -1) As IString
End Function
Public Property Get Value() As String
'Attribute Item.VB_UserMemId = 0
End Property
Public Property Let Value(v As String)
End Property
Public Property Get Length() As Long
End Property
Public Function Trim() As IString
End Function
StringEx クラス
メソッドチェーンにしたい場合、編集した結果をNewInstance メソッドで新しいインスタンスのStringExクラスを戻すようにする。(SubStringメソッド、Trimメソッドを参考)
このクラスをフォームと同じように、静的クラス(規定のインスタンス)で使えるようにする。
手順は以下の通り。
- クラスをエクスポートする。
- ソースのプロパティ「Attribute VB_PredeclaredId = False」をエディタ等で「True」に書き換える。
- VBEでインポートしなおす。
StringEx.NewInstance() というコンストラクタが使えるようになる。
Option Explicit
Implements IString
Private mBuf As String
Public Function NewInstance(ByVal s As String) As IString
Set NewInstance = New StringEx
NewInstance.Value = s
End Function
Private Property Get IString_Length() As Long
IString_Length = Len(mBuf)
End Property
Private Function IString_SubString(ByVal starts As Long, Optional ByVal ends As Long = -1) As IString
If ends = -1 Then
Set IString_SubString = Me.NewInstance(Mid$(mBuf, starts + 1))
Else
Set IString_SubString = Me.NewInstance(Mid$(mBuf, starts + 1, ends - starts))
End If
End Function
Private Function IString_Trim() As IString
Set IString_Trim = Me.NewInstance(Trim(mBuf))
End Function
Private Property Let IString_Value(RHS As String)
mBuf = RHS
End Property
Private Property Get IString_Value() As String
IString_Value = mBuf
End Property
自分で作ったライブラリの String 型の戻り値を この例を元に IString インターフェースを戻せば便利に使えると思う。
フリーソフトを作っています。
Excelを便利にする250以上の機能を体系化したアドインはこちらです。
「RelaxTools Addin」窓の杜大賞受賞ソフト
http://software.opensquare.net/relaxtools/