20240912エクセルVBA オブジェクト指向備忘録 クラスfunction 2つの答えを求める
<前書き>
エクセルVBAオブジェクト指向、初心者です。
VBA自体は、以前から使用していました。
オブジェクト指向というものがあることは、知っていましたが、ネットなどを見てもよく分からず、挫折した過去あり。
<以上前書き>
(素人なので間違っているかもしれません。汗。)
こんなエクセルファイルがあるとします。
単純に、マクロで、A列を検索し、
①合致するものがあるか?
②合致する場合、何行目か?
をメッセージボックスに出すコードです。
下記にいろんなパターンを書きました。
注:パブリック変数は使いません。
注:コード中に、検索する値を、
' targetnum = 301 'ここ書き換え(コメントアウトを切り替えて試しています)
targetnum = 201
直接書いてます。
【ケース1】(functionを使って①合致するものがあるか?を判断。クラス使わない。)
Option Explicit
'module1
Dim targetrow As Long
Function searchmatchingrow1() As Boolean
' Dim targetrow As Long
Dim targetnum As Long
Dim lastrow As Long
Dim i As Long
' targetnum = 301 'ここ書き換え
targetnum = 201
lastrow = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To lastrow
If Worksheets("Sheet1").Cells(i, 1).Value = targetnum Then
searchmatchingrow1 = True
Exit For
Else
searchmatchingrow1 = False
End If
Next i
End Function
----------------------------------------------
Sub main1() 'trueかfalseかを知りたい
Dim result1 As Boolean
result1 = searchmatchingrow1
MsgBox result1
End Sub
↑まあ、普通です。
ただ、プロシージャの外に、Dim targetrow As Longを置いて、変数を受け渡しています。
==============================================
【ケース1】の2(subを使って②合致する場合、何行目か?を判断。クラス使わない。)
Option Explicit
'module1
Dim targetrow As Long
Sub searchmatchingrow2() 'main2() から呼び出し
Dim targetnum As Long
Dim lastrow As Long
Dim i As Long
' targetnum = 301 'ここ書き換え
targetnum = 201
lastrow = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To lastrow
If Worksheets("Sheet1").Cells(i, 1).Value = targetnum Then
targetrow = i
Exit Sub
Else
End If
Next i
targetrow = 0
End Sub
----------------------------------------------------------
Sub main2() '該当行の行数を知りたい
Dim result2 As Long
Call searchmatchingrow2
' Dim targetrow As Long
result2 = targetrow
MsgBox result2
'エラー処理
'見つからない場合は0
End Sub
↑まあ、普通です。
ただ、プロシージャの外に、Dim targetrow As Longを置いて、変数を受け渡しています。
*******************************************************
【ケース2】の2(クラスを使用。メソッド(sub)を使って②合致する場合、何行目か?を判断。)失敗
Option Explicit
'class1
Sub searchmatchingrow2()
Dim targetnum As Long
Dim lastrow As Long
Dim i As Long
Dim targetrow As Long 'ここで宣言
' targetnum = 301 'ここ書き換え
targetnum = 201
lastrow = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To lastrow
If Worksheets("Sheet1").Cells(i, 1).Value = targetnum Then
targetrow = i
Exit Sub
Else
End If
Next i
targetrow = 0
End Sub
-----------------------------------
'Module2
Sub main3() '該当行の行数を知りたい ボツ(クラスのメソッドだけ使う)
Dim result3 As Long
Dim targetrow As Long 'ここで宣言
Dim vClass1 As Class1
Set vClass1 = New Class1
vClass1.searchmatchingrow2
'インスタンス化してもこれはtaegetrow渡らない
result3 = targetrow
MsgBox result3
'エラー処理
'見つからない場合は0
End Sub
↑これだと、クラスで、正しい答えが出ても、main3に渡せません。残念。
vClass1.searchmatchingrow2
'インスタンス化してもこれはtaegetrow渡らない
*********************************************
【ケース3】の2(クラスを使用。メソッド(sub)だけでなくプロパティを置いて②合致する場合、何行目か?を判断。)
Option Explicit
'Class2
'宣言
Private mtargetrow As Long
'
''let
'Public Property Let targetrow(ptargetrow As Long)
' mtargetrow = ptargetrow
'End Property
'get
Public Property Get targetrow() As Long
targetrow = mtargetrow
End Property
Sub searchmatchingrow3() ' (クラスのプロパティとメソッド使う)
Dim targetnum As Long
Dim lastrow As Long
Dim i As Long
' Dim mtargetrow As Long 'ここで宣言は間違い(でもエラー出ない)
' targetnum = 301 'ここ書き換え
targetnum = 201
lastrow = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To lastrow
If Worksheets("Sheet1").Cells(i, 1).Value = targetnum Then
mtargetrow = i
Exit Sub
Else
End If
Next i
mtargetrow = 0
End Sub
----------------------------------------------
Option Explicit
'module3
Sub main4() '該当行の行数を知りたい (動くOK)
Dim result4 As Long
Dim targetrow As Long 'ここで宣言
Dim vClass2 As Class2
Set vClass2 = New Class2
vClass2.searchmatchingrow3
result4 = vClass2.targetrow
MsgBox result4
'エラー処理
'見つからない場合は0
End Sub
↑これだと、動きます。クラスに、メソッドだけでなくプロパティを置いて、result4 = vClass2.targetrow
プロパティにアクセスします。
(関係ないですが、Dim mtargetrow As Long の宣言位置を間違ったり、重複させないように注意。エラーが出ればいいですが、出ない場合もある。別のスコープ範囲だからか???)
途中、functionを使用する①合致するものがあるか?を判断を書いていませんが、
クラスのプロパティとメソッド(sub)で②が取れるのが、分かったので、最後にメソッド(sub)をfunctionに変えて、①②の二つの答えを出せるようにします。
****************************************
【ケース4】(クラスを使用。メソッド(function)を使用。プロパティを置いて
①合致するものがあるか?を判断
②合致する場合、何行目か?を判断。)
Option Explicit
'class3
'宣言
Private mtargetrow As Long
'
''let
'Public Property Let targetrow(ptargetrow As Long)
' mtargetrow = ptargetrow
'End Property
'get
Public Property Get targetrow() As Long
targetrow = mtargetrow
End Property
Function searchmatchingrow4() As Boolean ' (クラスのプロパティとメソッド使う) functionにする
Dim targetnum As Long
Dim lastrow As Long
Dim i As Long
' Dim mtargetrow As Long 'ここで宣言は間違い(でもエラー出ない)
' targetnum = 301 'ここ書き換え
targetnum = 201
lastrow = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To lastrow
If Worksheets("Sheet1").Cells(i, 1).Value = targetnum Then
searchmatchingrow4 = True
mtargetrow = i
Exit Function
Else
searchmatchingrow4 = False
End If
Next i
mtargetrow = 0
End Function
----------------------------------------
'module4
Sub main5() '該当行の行数を知りたい (2つの使い方)
Dim result_exist As Boolean
Dim result5 As Long
Dim targetrow As Long 'ここで宣言
Dim vClass3 As Class3
Set vClass3 = New Class3
' vClass3.searchmatchingrow4
result_exist = vClass3.searchmatchingrow4
MsgBox result_exist
result5 = vClass3.targetrow
MsgBox result5
'エラー処理
'見つからない場合は0
End Sub
↑result_exist = vClass3.searchmatchingrow4でboolean型
result5 = vClass3.targetrowでlong型
の変数を取ってます。
考え:
②合致する行数が取れれば(0より大きい)、①一致する値があることも分かるので、あまり意味がないかもしれないが、
後から、機能を追加する場合は、楽かも。
関係ないが、オブジェクト指向を学習するのに、ワークシートファンクションをあまり使わないように考えてきたが、せっかくのエクセルの機能なので、使っていこうかなと思います。