vba【コールバックぽく処理を記述】
たとえば、findnextを使って、検索にヒットするすべてのセルに処理を行いたいとします。
こういう時は、コールバックが使えたら便利だなと思っていました。
ただvbaにコールバック関数的なものがあるのか分かりませんが、callbyname関数があってこれを使うとそれっぽくできるとのことなのでやってみたメモを残します。
コールバックする関数はクラスモジュールのCommonMethodsというクラスを作って、そこにパブリックメソッドとして記述します。
第1引数に検索でhitしたセル(findAll関数から渡される)
第2引数にコールバックの大元から送った引数(mainサブルーチンから渡される)
Public Sub changeColor(ByVal fcell As Range, ByRef co As Collection) fcell.Interior.ColorIndex = co(1) End Sub
findnextのループを行う関数はつぎのようになります。
標準モジュールや、クラスモジュールの場合はメソッドとして記述します。
第1引数に検索範囲
第2引数に検索テキスト
第3引数にコールバック関数名のstring
第4引数にコールバック関数に渡す引数のCollection
Private Sub findAll(ByVal ra As Range, ByVal whattxt As String, ByVal callback As String, ByVal callback_args As Collection) Dim fcell As Range Dim fadd As String Set fcell = ra.Find(what:=whattxt, LookIn:=xlValues, lookat:=xlWhole, MatchCase:=True) If Not fcell Is Nothing Then fadd = fcell.Address Do CallByName New CommonMethods, callback, VbMethod, fcell, callback_args Set fcell = ra.FindNext(fcell) If fcell Is Nothing Then Exit Do End If If fcell.Address = fadd Then Exit Do End If Loop End If End Sub
あとはmainから呼び出します。
Sub main() Dim callback_args As New Collection callback_args.Add 10 Call findAll(Cells, "test", "changeColor", callback_args) End Sub
コールバック関数をクラスモジュールに書いているのが若干気持ち悪いです。
javascriptのように無名関数を渡せると非常に勝手がいいなと思いますが、まあそこまでなくても希望の動きはできました。