みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。
「初心者向けエクセルVBAではじめてのクラスモジュール」についてシリーズでお伝えしています。
前回の記事はこちら。
自作のコレクションから要素を削除するメソッドを追加しました。
さて、エクセル表を表すクラスを作ってそれをオブジェクトとして操作するのはいいのですが、操作した結果をエクセル表に反映させなくてはいけませんよね。
ということで、今回はシリーズ最終回。
エクセルVBAで自作コレクションのデータをエクセル表に反映させるメソッドの作り方をお伝えします。
では、行ってみましょう!
前回のおさらい
では、前回のおさらいからです。
以下のようなエクセル表があります。
このエクセル表のデータを取り扱うクラスを作成しておりますが、まずは1行分のデータを表すクラスPersonがこちらです。
Private id_ As String
Public FirstName As String
Public Gender As String
Public Birthday As Date
Public Sub Greet()
MsgBox Me.FirstName & "です、こんにちは!"
End Sub
Public Sub Initialize(ByVal values As Variant)
Select Case TypeName(values)
Case "Range"
id_ = values(1).Value
FirstName = values(2).Value
Gender = values(3).Value
Birthday = values(4).Value
Case "Variant()"
id_ = values(0)
FirstName = values(1)
Gender = values(2)
Birthday = values(3)
End Select
End Sub
Public Property Get IsMale() As Boolean
IsMale = (Me.Gender = "male")
End Property
Public Property Get Id() As String
Id = id_
End Property
Public Property Let Id(ByVal newId As String)
If id_ <> "" Then
Debug.Print "Idは上書きすることはできません"
Else
id_ = newId
End If
End Property
フィールドを表すプロパティのほか、便利そうなメンバーをいくつか追加しております。
そして、それを集合として扱うために、自作コレクションを作りました。それが、以下のPersonsクラスになります。
Private items_ As Collection
Private Sub Class_Initialize()
Set items_ = 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
Public Property Get Item(ByVal key As Variant) As Person
Set Item = items_.Item(key)
End Property
Public Function Add(ByVal values As Variant) As Person
Dim p As Person: Set p = New Person
p.Initialize values
items_.Add p, p.Id
Set Add = p
End Function
Public Sub Remove(ByVal key As Variant)
items_.Remove key
End Sub
このPersonsコレクションは、Personオブジェクトを集合として取り扱うものなので、結果としてPersonsコレクションがエクセル表のデータ全体を表します。
前回は、このPersonsコレクションから要素を削除するRemoveメソッドを作成しました。
それを検証するための標準モジュールがこちらです。
Sub MySub()
Dim myPersons As Persons: Set myPersons = New Persons
Dim p As Person
Set p = myPersons.Add(Array("a04", "Jay", "male", #7/7/1995#))
With myPersons
.Remove 2
.Remove "a01"
End With
Stop
End Sub
データをオブジェクトで操作した結果をエクセル表に反映する
これで、なんとなくエクセル表のデータをクラス化して取り扱う全体の機能ができた感じです。
手順としては、以下の通り。
- エクセル表をもとに新規のPersonsコレクションを生成する
- Personsコレクションの要素を追加したり、削除したり、変更したりする
- Personsコレクションを再度エクセル表に反映する
こんな流れですね。
2の操作とかを、さらにユーザーフォームとかを使って操作できるようにしたら、アプリケーションぽい感じになります。
それで、お気づきの通り、3のPersonsコレクションを操作した結果をエクセル表に反映させるという処理がまだありませんので、今回はそれを作っていきます。
Personsコレクションのデータをエクセル表に反映する
Personsコレクションのデータをエクセル表に反映させるApplyToSheetメソッドを作成します。
戻り値などは必要ないので、Subプロシージャで作ります。
Public 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 p As Person
For Each p In items_
.Range(.Cells(i, 1), .Cells(i, 4)) = Array(p.Id, p.FirstName, p.Gender, p.Birthday)
i = i + 1
Next p
End With
End Sub
流れとしては以下のとおりですね。
- Sheet1をいったんクリア
- 1行目に見出しを再度書き出す
- Personsコレクションの要素の数だけ繰り返して
- 各要素のデータをエクセル表に書き出す
- 行を1つ追加
エクセル表への反映について動作確認
作成したPersonsコレクションのApplyToSheetメソッドの動作を確認します。
例えば、標準モジュールに以下のようなSubプロシージャを作りました。
Sub MySub()
Dim myPersons As Persons: Set myPersons = New Persons
With myPersons
.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
確認をすると…
バッチリですね!
結局、クラスを使うと何がいいのか
さて、これまで19記事も使ってクラスを作ってきたのですが、エクセル表の操作になぜここまでゴチャゴチャする必要があるのか…と思いますか?
わざわざクラスを使う必要ないじゃないか…!?
と思ったりしますでしょうか。
このマクロには、エクセル表のデータを新規コレクションのインスタンスに取り込んだり、「こんにちは!」とメッセージを表示したり、男性かどうかを判定したり、追加したり、削除したり…といった機能があります。
ですが、前述の動作確認用の標準モジュールのコードを見ていただくと、想像以上にスッキリしていませんか?
色々な機能を実現するステートメントは、すべてクラスモジュールにかかれていますので、標準モジュール上では一切目にする必要がありません。
標準モジュールでは、それらの機能にアクセスするためのメンバーを呼び出すことしかしていないんです。
つまり、マクロのうち「機能」の部分をクラスモジュールに分離するということが実現できているのです。
おかげで、標準モジュールは、その機能を「操作」をするだけの役割に徹することができるのです。
- 機能:クラスモジュール
- 操作:標準モジュール
さらに、このエクセル表に何か新しい操作をしたくなったら、それもクラスモジュールに追加します。
マクロの機能は増えても、標準モジュールのステップ数を極小に保つことができます。
スッキリしますでしょ?
まとめ
以上、エクセルVBAで自作コレクションのデータをエクセル表に反映させるメソッドの作り方をお伝えしました。
また、ただのエクセル表をクラスとして取り扱うメリットについても触れました。
エクセル表を保護して、これらのクラスのメンバーをユーザーフォームなどで扱えるようにすると、さらにアプリケーションぽくなりますね。
さて、使い捨てのマクロでればクラス化はおそらく必要ありませんが、長いことお付き合いするデータ群であれば、クラス化をするとスッキリ管理と運用ができて、使い勝手も良くなるかも知れません。
ぜひ、検討をしてみてくださいね。
本シリーズは以上で終了となります。また、別のシリーズでエクセルVBAの活用法についてお伝えしていきますので、どうぞお楽しみに!
連載目次:初心者でもわかる!エクセルVBAでクラスを作ろう
名前は聞いたことあるけどよくわからない「クラスモジュール」。本シリーズでは、初心者でも少しずつ丁寧にその作り方と便利さについてお伝えしていきますよ!- 【初心者でもできる】エクセルVBAで最も簡単なクラスを作る方法
- エクセルVBAでクラスに最も簡単なプロパティを追加する方法
- エクセルVBAで自作クラスをインスタンス化する方法
- エクセルVBAでクラスに最も簡単なメソッドを追加する方法
- エクセルVBAで表の1行分のデータを表すクラスを作成する方法
- エクセルVBAでProperty Getプロシージャを使って簡単なプロパティを作成する方法
- エクセルVBAでプロパティを他のモジュールからアクセスできないようにする方法
- エクセルVBAでProperty Letプロシージャを使ってプロパティ設定をする方法
- エクセルVBAでPropety Getプロシージャを使ってプライベート変数にアクセスする方法
- エクセルVBAでクラスのインスタンス生成時に初期データを格納するメソッドを作る方法
- エクセルVBAでインスタンスの集合をコレクション化する方法
- エクセルVBAでコレクション化したインスタンスを取り出す方法
- エクセルVBAでクラスモジュールを使って独自のコレクションを作る方法
- エクセルVBAでインスタンス生成時に自動で処理を実行するイベントプロシージャClass_Initialize
- エクセルVBAで自作コレクションのインスタンス生成時に初期データも投入する方法
- エクセルVBAで自作コレクションの要素を取得するプロパティの作り方
- エクセルVBAで自作のコレクションに要素を追加するメソッドを作成する
- エクセルVBAで自作コレクションの要素を削除するメソッドの作り方
- エクセルVBAでエクセル表のデータを反映するメソッドとクラスを使うメリット