エクセルVBA オブジェクト指向備忘録  クラスfunction 2つの答えを求める(あまり意味なし)

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より大きい)、①一致する値があることも分かるので、あまり意味がないかもしれないが、
後から、機能を追加する場合は、楽かも。


関係ないが、オブジェクト指向を学習するのに、ワークシートファンクションをあまり使わないように考えてきたが、せっかくのエクセルの機能なので、使っていこうかなと思います。