この記事では
- VBAのクラスモジュールの使い方を解説しています。
- 前回に引き続き、シートの情報をクラスモジュールを使ってオブジェクト化していく手法を説明しています。
- 前回までのコードを整理しています。
- この記事はクラスモジュールの実践的な使い方を学びたい人に向けて書いています。
- シリーズものです。その1はこちら→挫折した人のためのVBAクラスモジュール入門_その1 - 適材適所。
今回は具体的な話を
前回はプロパティのカプセル化とインターフェースの統一化についてでした。
抽象的な話になってしまったので、具体的な話に戻していきます。
今回は、GodExcelオブジェクトのプロパティの定義をクラスモジュールにやっていきたいと思います。
神エクセルの仕様
GoeExcelオブジェクトのプロパティについて考えるにあたり、改めて神エクセルがどんなものだったか再掲します。
そうそう、こんなワークシートでした。
改めて見ると、やっぱり酷いですね・・・。
シートの情報としては、こんな感じになっております。
名前フリガナ B6~U6 名前漢字 B8~U8 生年月日年 B12~E12 生年月日月 F12~G12 生年月日日 H12~I12 郵便番号1 B16~D16 郵便番号2 F16~I16 住所 B18~U19 メールアドレスB22~U23 勤務先名称 B26~N26 職業 P26~U26
GodExcelオブジェクトは、これらの情報を持つオブジェクトとしたいのでした。
これまでのProperty Let/Getを使うとこんな風にクラスを定義できます。
ちょっと長いです。
'GodExcel.cls 'プロパティ Private pNameFurigana As String Private pNameKanji As String Private pBirthDay As Date Private pPostalCode As String Private pAddress As String Private pMailAddress As String Private pWorkPlace As String Private pProffsion As String Public Property Get NameFurigana() As String NameFurigana = pNameFurigana End Property Public Property Let NameFurigana(aNameFurigana As String) pNameFurigana = aNameFurigana End Property Public Property Get NameKanji() As String NameKanji = pNameKanji End Property Public Property Let NameKanji(aNameKanji As String) pNameKanji = aNameKanji End Property Public Property Get BirthDay() As Date BirthDay = pBirthDay End Property Public Property Let BirthDay(aBirthDay As Date) pBirthDay = aBirthDay End Property Public Property Get PostalCode() As String PostalCode = pPostalCode End Property Public Property Let PostalCode(aPostalCode As String) pPostalCode = aPostalCode End Property Public Property Get Address() As String Address = pAddress End Property Public Property Let Address(aAddress As String) pAddress = aAddress End Property Public Property Get MailAddress() As String MailAddress = pMailAddress End Property Public Property Let MailAddress(aMailAddress As String) pMailAddress = aMailAddress End Property Public Property Get WorkPlace() As String WorkPlace = pWorkPlace End Property Public Property Let WorkPlace(aWorkPlace As String) pWorkPlace = aWorkPlace End Property Public Property Get Proffsion() As String Proffsion = pProffsion End Property Public Property Let Proffsion(aProffsion As String) pProffsion = aProffsion End Property
次に、このクラスからオブジェクトを生成して、そのオブジェクトに値をセットして出力するプログラムはこんな感じでしょうか。
Const NAME_FURI_RNG As String = "B6:U6" Const NAME_KAN_RNG As String = "B8:U8" Const BIRTH_Y_RNG As String = "B12:E12" Const BIRTH_M_RNG As String = "F12:G12" Const BIRTH_D_RNG As String = "H12:I12" Const POST1_RNG As String = "B16:D16" Const POST2_RNG As String = "F16:I16" Const ADR_RNG As String = "B18:U19" Const MAIL_RNG As String = "B22:U23" Const WORK_PLACE_RNG As String = "B26:N26" Const PROFFESION_RNG As String = "P26:U26" Sub sample() Dim god As GodExcel Set god = New GodExcel '値を設定 god.NameFurigana = getItem(Range(NAME_FURI_RNG)) god.NameKanji = getItem(Range(NAME_KAN_RNG)) god.BirthDay = DateSerial(getItem(Range(BIRTH_Y_RNG)), _ getItem(Range(BIRTH_M_RNG)), _ getItem(Range(BIRTH_D_RNG))) god.PostalCode = getItem(Range(POST1_RNG)) & getItem(Range(POST2_RNG)) god.Address = getItem(Range(ADR_RNG)) god.MailAddress = getItem(Range(MAIL_RNG)) god.WorkPlace = getItem(Range(WORK_PLACE_RNG)) god.Proffsion = getItem(Range(PROFFESION_RNG)) 'イミディエイトウィンドウに出力 Debug.Print god.NameFurigana Debug.Print god.NameKanji Debug.Print god.BirthDay Debug.Print god.PostalCode Debug.Print god.Address Debug.Print god.MailAddress Debug.Print god.WorkPlace Debug.Print god.Proffsion End Sub
'ヘルパー関数 Private Function getItem(aRng As Range) As String Dim recString As String Dim i As Long For i = 1 To aRng.Count Dim r As Range: Set r = aRng.Item(i) recString = recString & r.Value Next i getItem = recString End Function
これは・・・。
どうでしょう?標準モジュールで値をセットしているこのコード・・・。
これじゃない感がすごいです。
もっと、こう、なんというんでしょう、オブジェクトを生成した時点で、オブジェクトは値を知っていて、それを出力するだけってのが本当の理想だと思います。
これでは、オブジェクトへの値の設定の責任はオブジェクトの外にある状態です。
値の設定までの責任をオブジェクトに持たせるためには、オブジェクトが生成される時点で自動的に呼ばれる、コンストラクタと呼ばれるものにその処理を定義してあげます。
コンストラクタを定義する
VBAのクラスモジュールでコンストラクタを定義するためには、次の手順で行います。
まず、VBEのコードエディタの上部のタブをクリックし、Classを指定します
次にその隣をInitalizeに設定すると、Class_Initializeサブプロシージャが生成されます。
このClass_Initalizeサブプロシージャは特別なサブプロシージャで、オブジェクトが生成されるときに必ず呼ばれます。
GodExcelオブジェクトの例で言うと、オブジェクト生成時にここで値を全て設定してあげれば、あとは設定する手間が省けます。
そうすることで、GodExcelオブジェクトを外部から呼び出すプログラムは、GodExcelオブジェクトを生成するだけで、値を取得することができます。
また、ワークシートのどの範囲がどの値なのかを外部のプログラムは意識する必要がありません。
これでワークシートの位置情報がカプセル化されている状態になり、ワークシートのセル範囲を変更した際は、このクラスの定義だけを変更すれば他のプログラムには影響が出ません。
さきほどの標準モジュールに定義したプログラムを使って、コンストラクタを定義してみます。
'コンストラクタ Private Sub Class_Initialize() '定数の定義は省略 pNameFurigana = getItem(Range(NAME_FURI_RNG)) pNameKanji = getItem(Range(NAME_KAN_RNG)) pBirthDay = DateSerial(getItem(Range(BIRTH_Y_RNG)), _ getItem(Range(BIRTH_M_RNG)), _ getItem(Range(BIRTH_D_RNG))) pPostalCode = getItem(Range(POST1_RNG)) & getItem(Range(POST2_RNG)) pAddress = getItem(Range(ADR_RNG)) pMailAddress = getItem(Range(MAIL_RNG)) pWorkPlace = getItem(Range(WORK_PLACE_RNG)) pProffsion = getItem(Range(PROFFESION_RNG)) End Sub
'ヘルパー関数 Private Function getItem(aRng As Range) As String Dim recString As String Dim i As Long For i = 1 To aRng.Count Dim r As Range: Set r = aRng.Item(i) recString = recString & r.Value Next i getItem = recString End Function
これで、GodExcelオブジェクトが生成された時点で、値が設定されているはずです。
いざテスト!!
テストしてみる
テスト対象のワークシートはこうしました。
標準モジュールはオブジェクトを生成して、その値を出力すだけにします。
Sub sampleTest() Dim god As GodExcel Set god = New GodExcel Debug.Print god.NameFurigana Debug.Print god.NameKanji Debug.Print god.BirthDay Debug.Print god.PostalCode Debug.Print god.Address Debug.Print god.MailAddress Debug.Print god.WorkPlace Debug.Print god.Proffsion End Sub
実行結果(イミディエイトウィンドウ)
テスト 手酢徒 2000/01/01 1000004 東京都千代田区大手町1-1 sample@sample.co.jp サンプル株式会社 営業
おお、これです、これ!
標準モジュールがキレイです!!
標準モジュールでは、ただGodExcelオブジェクトを生成しているだけです。
GodExcelオブジェジェクト内部で何が行われているかは呼び出し元であるsampleTestは知らない状態です。
知っているのは外部に公開されているプロパティだけです。
つまり、GodExcelオブジェクトの中にシートの情報を隠蔽(カプセル化)することができました。
なんだかいい感じのオブジェクトになってきました。これぞクラスモジュールを使っている感がありますね。
これでGodExcelオブジェクトもかなりレベルアップしました。Lv30くらいですねかね。
シートの情報は構造化され、GodExcelオブジェクトを通して情報を知ることができるようになりました。
また、セルの位置が変わっても、変更箇所はこのGodExcelオブジェクトを定義するクラスモジュールだけで済みます。
あと少しでGodExcelオブジェクトも完成し、神になれます、きっと。
今回は盛沢山でした。コンストラクタについて早足すぎましたので、一旦GodExcelオブジェクトから離れて、次回はもうコンストラクタの話をしたいと思います。
ここまでお読みいただきありがとうございました。