エクセルVBA オブジェクト指向備忘録クラス002

20240203エクセルVBA オブジェクト指向備忘録クラス002
エクセルVBA オブジェクト指向備忘録
 
<前書き>
エクセルVBAオブジェクト指向、初心者です。
VBA自体は、以前から使用していました。
オブジェクト指向というものがあることは、知っていましたが、ネットなどを見てもよく分からず、挫折した過去あり。
 
エクセルVBAで、オブジェクト指向を必要とすることもなかったので、諦めていましたが、
youtubeで、「ひとりごとワンダーランド」様のエクセルVBAでのクラスに関する動画を見させていただき、
少しだけやる気になっています。感謝。
(まだ、動画は最後まで見ていません。汗)
<以上前書き>
 
 
前回に引き続き、以下自分用のメモ。
 
 
youtube「ひとりごとワンダーランド」様のクラスモジュールの作法(なるべくprivateでpublicを減らすとか、クラス内変数の書き方とか)を
使って、ネットHPで「いつも隣にITのお仕事」様の記事「エクセルVBAでエクセル表のデータを反映するメソッドとクラスを使うメリット」を
コード化しました。
分かっていないので、間違っているかも。(多分、間違っている。汗)
注:もしこのブログ記事に関し、youtube「ひとりごとワンダーランド」様、ネットHP「いつも隣にITのお仕事」様におかれまして、不都合があり、削除すべき場合は、即削除いたします。
 
コードの内容は、エクセルシート上のデータに対し、モジュールから削除や追加、修正を行うものです。
(自分のコメントも少し入ってます。)
 
////////////////////////////
(1)標準モジュール
Sub Mysub()
    Dim vPersons As Persons  '独自クラス
    Set vPersons = New Persons 'クラス生成 先にvPersons生成(Class_Initialize()動く)
    
    
    With vPersons
'データ追加
        .Add (Array("a04", "Jay", "male", #7/7/1995#))
        'データ削除
        .Remove 2
        'データ修正
        With .Item("a01")
            .FirstName = "Bomb"
            .Birthday = #11/11/1993#
        End With
        'エクセルシートに新規書き換え
        .ApplyToSheet
    End With
End Sub
 
 
 
 
///////////////////////////////////
(2)クラス「Person」
'privateで作る・・・もしかして、書き換えが必要な項目はpublicでいい?(取り出すのにgetなしでいいから・・・)
Private mId As String
Private mFirstName As String
Private mGender As String
Private mBirthday As Date
 
Public Sub Initialize(values As Variant) 
 'クラスinitializeではなくメソッドで初期化 
'(VBAのクラスinitializeは、(コンストラクタ)引数持てないらしい。定数?)
                                    
    Select Case TypeName(values)
        Case "Range"
            mId = values(1).Value
            mFirstName = values(2).Value
            mGender = values(3).Value
            mBirthday = values(4).Value
        Case "Variant()"                '"Variantはダメ"
            mId = values(0)
            mFirstName = values(1)
            mGender = values(2)
            mBirthday = values(3)
    End Select
End Sub
 
Property Get Id() As String  '省略するとpublic 'privateだとエラー
    Id = mId      '反対になる
End Property
 
Property Get FirstName() As String   
    FirstName = mFirstName   
End Property
 
 
Property Get Gender() As String   
    Gender = mGender    
End Property
 
 
Property Get Birthday() As Date   
    Birthday = mBirthday    
End Property
 
 
Property Get IsMale() As Boolean
    IsMale = (mGender = "male")
End Property
 
 
Property Let Id(pId As String)
    If mId <> "" Then
        Debug.Print "IDは上書き不可"
    Else
         mId = pId
    End If
End Property
 
 
Property Let FirstName(pFirstName As String)
     mFirstName = pFirstName
End Property
 
 
Property Let Gender(pGender As String)
     mGender = pGender
End Property
 
Property Let Birthday(pBirthday As Date)
     mBirthday = pBirthday
End Property
 
 
 
 
////////////////////////////////////////
(3)クラス「Persons」
Private mItems As Collection   'privateにする
 
Private Sub Class_Initialize()
    Set mItems = New Collection
    
    With Sheet1
        Dim i As Long
        i = 2
        Do While .Cells(i, 1).Value <> ""
 
            Me.Add .Range(.Cells(i, 1), .Cells(i, 4))
            
            i = i + 1
        Loop
   End With
End Sub
 
 
Property Set Items(pItems As Collection)
    Set mItems = pItems
End Property
 
'シンプルにaddメソッド追加を直し
Function Add(values As Variant) As person
    Dim mPerson As person
    Set mPerson = New person  'perosnクラスをインスタンス
 
    mPerson.Initialize values
    
    mItems.Add mPerson, mPerson.Id   
    
    Set Add = mPerson
End Function    
 
 
Property Get Items() As Collection
    Set Items = mItems
End Property
 
Property Get Item(key As Variant) As person
    Set Item = mItems.Item(key)
End Property
 
 
Sub Remove(key As Variant)
    mItems.Remove key
End Sub
 
 
Sub ApplyToSheet()
    With Sheet1
        .Cells.Clear
        .Range(.Cells(1, 1), .Cells(1, 4)) = Array("Id", "FirstName", "Gender", "Birthday")
       
        Dim i As Long: i = 2
        Dim mPerson As person
        For Each mPerson In mItems
            .Range(.Cells(i, 1), .Cells(i, 4)) = Array(mPerson.Id, mPerson.FirstName, mPerson.Gender, mPerson.Birthday)
            i = i + 1
        Next mPerson
    End With
End Sub
 
**********************************************
主に、2と3のクラスで、privateを多くしたのが、工夫点かもしれません。
(スコープ「public」と「private」についての使い方)
 
そのために、クラスがごちゃごちゃしました。
(きちんとした使い方なのか、後から考えてみます。)
 
その他、書き方ですが、手続き型(プロシージャ型)は、主に上から下へ、書いていく感じ(あまり削除しない)ですが、
クラスは、クラスと標準モジュールを行ったり来たり。
以前書いたものを、ばっさり削ったり、どんどん変わっていく(クラスに機能を追加したり、移すから?)感じがします。
 
(あと、クラスにprivateでメンバ変数を使うと、コード実行中に扱う変数の数がすごく多くなるのが気になりました。)
 
素人なので、分かりませんが。
 
 
追記
「いつも隣にITのお仕事」の記事に、「ユーザーフォームで扱えるようにすると・・・」と書いてありました。
できたら、標準モジュールに書いた値・命令などをユーザーフォームで、入力・実行できるといいな。