<前書き>
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ではなくメソッドで初期化
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のお仕事」の記事に、「ユーザーフォームで扱えるようにすると・・・」と書いてありました。
できたら、標準モジュールに書いた値・命令などをユーザーフォームで、入力・実行できるといいな。