Quantcast
Channel: いつも隣にITのお仕事
Viewing all articles
Browse latest Browse all 2078

エクセルVBAでクラスのインスタンス生成時に初期データを格納するメソッドを作る方法

$
0
0

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

「初心者でもわかるエクセルVBAのクラスモジュール」についてシリーズでお伝えしています。

前回の記事はこちらです。

エクセルVBAでProperty Letプロシージャを使ってプロパティ設定をする方法
「初心者でもわかるエクセルVBAのクラスモジュール」について連載でお送りしております。今回はエクセルVBAでProperty Letプロシージャを使ってプロパティ設定をする方法をお伝えします。

Property Letプロシージャの使い方をお伝えしました。

これで、クラスの作り方とPropertyプロシージャの使い方の超基本部分は抑えられたかなと思います。

が、作ってきたのはエクセル表の1行分を表すクラスです。

複数行をクラスを活かして扱うにはどうしたらよいでしょうか。

ということで、今回からコレクションの特性を持つクラスの作り方を目指していきますので、もうしばらくお付き合いください。

まず今回ですが、その前準備として、エクセル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 Property Get IsMale() As Boolean
    IsMale = (Me.Gender = "male")
End Property

Public Property Let Id(ByVal newId As String)
    If id_ <> "" Then
        Debug.Print "Idは上書きすることはできません"
    Else
        id_ = newId
    End If
End Property

上記コードにより、クラスに以下のメンバーを追加しています。

  • FirstNameプロパティ、Genderプロパティ、Birthdayプロパティはパブリック変数によるプロパティ
  • IdプロパティはProperty Letプロシージャにより、一度だけその値をプライベート変数id_にセットができます
  • IsMaleプロパティはProperty Getプロシージャによる読み取り専用のプロパティです
  • メソッドはGreetという挨拶代わりのメソッドですね

それを検証するための、Subプロシージャは以下の標準モジュールModule1に記載されています。

Sub MySub()

Dim p As Person: Set p = New Person

Dim i As Long: i = 2
With Sheet1
    p.Id = .Cells(i, 1).Value
    p.FirstName = .Cells(i, 2).Value
    p.Gender = .Cells(i, 3).Value
    p.Birthday = .Cells(i, 4).Value
End With

p.Id = "Hoge"
Stop
'p.Greet

End Sub

これからやりたいこと:複数行のデータをクラスで扱いたい

さて、これで1行分のデータに関してはクラスで扱えるようになりました。

ですが、エクセル表には、Bob以外のPersonもいらっしゃるわけで、それらをクラスとして扱おうと思ったら、以下のように人数分のインスタンスを用意しなければいけない…となると、ちょっとだるいです。

  • エクセル表のデータ行の分だけ以下繰り返す
    1. Personクラスのインスタンスを生成する
    2. インスタンスにエクセル表からデータを取り込む

標準モジュールに、ループ処理を作ってもいいのですが、これ…どうせ必要ならクラスの機能として持っておいたほうがスッキリしますよね。

それで、今回は2の「インスタンスにエクセル表からデータを取り込む」という処理をクラスモジュールPersonの処理として寄せてしまいたいと思います。

インスタンスの初期データをセットするメソッド

VBAにはコンストラクタがない

実は、他の言語でいうと、インスタンスの生成とデータの初期化がいっぺんに行える言語が多くあります。

一般的にコンストラクタと呼ばれる関数です。

コンストラクタを作成しておくと、インスタンスを生成したときに自動的に呼び出されて、必要なデータをセットできるのです。

残念ながらVBAにはコンストラクタのような機能は存在していません…。

ただ、どうせインスタンスを生成してから初期データをセットするのであれば、それを楽に行えるメソッドは作っておいて損はないですよね。

インスタンスの初期化をするメソッド

今回、データはエクセル表に展開されています。

ですから、その1行分のデータ範囲つまりRangeオブジェクトを渡したら、それをプロパティにセットしてくれるようにしてくれればシンプルに作れそうです。

クラスモジュールPersonに、以下のようなSubプロシージャInitializeを追加して、Initializeメソッドを作ります。

Public Sub Initialize(ByVal rng As Range)
    id_ = rng(1).Value
    FirstName = rng(2).Value
    Gender = rng(3).Value
    Birthday = rng(4).Value
End Sub

1行分のセル範囲をRangeオブジェクトで受け取って、左上のセルの値から順に、id_、FirstName、Gender、Birthdayにセットをします。

エクセル表の列順さえ入れ替わることがなければ、これでいけそうです。

Initializeメソッドの動作確認

では、標準モジュールModule1を以下のように変更して、その動作を確認してみましょう。

Sub MySub()

Dim i As Long: i = 2
Dim p As Person: Set p = New Person
With Sheet1
    p.Initialize .Range(.Cells(i, 1), .Cells(i, 4))
End With

Stop
'p.Greet

End Sub

Stopステートメントで中断しているときに、ローカルウィンドウを確認してみると、以下のようにすべてのプロパティが正しくセットされていることが確認できます。

エクセルVBAのインスタンスの初期データを確認する

まとめ

以上、エクセルVBAでクラスのインスタンス生成時にデータを簡単に格納するメソッドを作る方法をお伝えしました。

VBAにはインスタンス生成時にデータを初期化するコンストラクタがないので、その代わりになるメソッドを独自で作成する必要があります。

さて、次回はエクセル表の他のデータも取り扱えるようにコレクションを活用していきます。

どうぞお楽しみに!

連載目次:初心者でもわかる!エクセルVBAでクラスを作ろう

名前は聞いたことあるけどよくわからない「クラスモジュール」。本シリーズでは、初心者でも少しずつ丁寧にその作り方と便利さについてお伝えしていきますよ!
  1. 【初心者でもできる】エクセルVBAで最も簡単なクラスを作る方法
  2. エクセルVBAでクラスに最も簡単なプロパティを追加する方法
  3. エクセルVBAで自作クラスをインスタンス化する方法
  4. エクセルVBAでクラスに最も簡単なメソッドを追加する方法
  5. エクセルVBAで表の1行分のデータを表すクラスを作成する方法
  6. エクセルVBAでProperty Getプロシージャを使って簡単なプロパティを作成する方法
  7. エクセルVBAでプロパティを他のモジュールからアクセスできないようにする方法
  8. エクセルVBAでProperty Letプロシージャを使ってプロパティ設定をする方法

Viewing all articles
Browse latest Browse all 2078

Trending Articles