エクセルVBAでエクセル表のデータを反映するメソッドとクラスを使うメリット


separate

みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。

「初心者向けエクセルVBAではじめてのクラスモジュール」についてシリーズでお伝えしています。

前回の記事はこちら。

エクセルVBAで自作コレクションの要素を削除するメソッドの作り方
「初心者でもわかるエクセルVBAのクラスモジュール」シリーズをお送りしています。今回は、エクセルVBAで自作コレクションの要素を削除するRemoveメソッドの作り方についてお伝えしていきます。

自作のコレクションから要素を削除するメソッドを追加しました。

さて、エクセル表を表すクラスを作ってそれをオブジェクトとして操作するのはいいのですが、操作した結果をエクセル表に反映させなくてはいけませんよね。

ということで、今回はシリーズ最終回。

エクセル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

データをオブジェクトで操作した結果をエクセル表に反映する

これで、なんとなくエクセル表のデータをクラス化して取り扱う全体の機能ができた感じです。

手順としては、以下の通り。

  1. エクセル表をもとに新規のPersonsコレクションを生成する
  2. Personsコレクションの要素を追加したり、削除したり、変更したりする
  3. 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

流れとしては以下のとおりですね。

  1. Sheet1をいったんクリア
  2. 1行目に見出しを再度書き出す
  3. Personsコレクションの要素の数だけ繰り返して
    1. 各要素のデータをエクセル表に書き出す
    2. 行を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でクラスを作ろう

名前は聞いたことあるけどよくわからない「クラスモジュール」。本シリーズでは、初心者でも少しずつ丁寧にその作り方と便利さについてお伝えしていきますよ!
  1. 【初心者でもできる】エクセルVBAで最も簡単なクラスを作る方法
  2. エクセルVBAでクラスに最も簡単なプロパティを追加する方法
  3. エクセルVBAで自作クラスをインスタンス化する方法
  4. エクセルVBAでクラスに最も簡単なメソッドを追加する方法
  5. エクセルVBAで表の1行分のデータを表すクラスを作成する方法
  6. エクセルVBAでProperty Getプロシージャを使って簡単なプロパティを作成する方法
  7. エクセルVBAでプロパティを他のモジュールからアクセスできないようにする方法
  8. エクセルVBAでProperty Letプロシージャを使ってプロパティ設定をする方法
  9. エクセルVBAでPropety Getプロシージャを使ってプライベート変数にアクセスする方法
  10. エクセルVBAでクラスのインスタンス生成時に初期データを格納するメソッドを作る方法
  11. エクセルVBAでインスタンスの集合をコレクション化する方法
  12. エクセルVBAでコレクション化したインスタンスを取り出す方法
  13. エクセルVBAでクラスモジュールを使って独自のコレクションを作る方法
  14. エクセルVBAでインスタンス生成時に自動で処理を実行するイベントプロシージャClass_Initialize
  15. エクセルVBAで自作コレクションのインスタンス生成時に初期データも投入する方法
  16. エクセルVBAで自作コレクションの要素を取得するプロパティの作り方
  17. エクセルVBAで自作のコレクションに要素を追加するメソッドを作成する
  18. エクセルVBAで自作コレクションの要素を削除するメソッドの作り方
  19. エクセルVBAでエクセル表のデータを反映するメソッドとクラスを使うメリット

タイトルとURLをコピーしました