適材適所

WindowsやPowerShellやネットワーク、IBMなどのシステム系の話やポイ活など気になったことも載せているブログです。

挫折した人のためのVBAクラスモジュール入門_その9

この記事では

  • VBAのクラスモジュールの使い方を解説しています。
  • ワークシートの情報をオブジェクト化する際のより実践的なアイディアを紹介しています。
  • この記事はクラスモジュールの実践的な使い方を学びたい人に向けて書いています。
  • シリーズものです。その1はこちら→挫折した人のためのVBAクラスモジュール入門_その1 - 適材適所

GodExcelオブジェクトの現在の状態

前回はGodExcelオブジェクトから離れて、コンストラクタとデストラクタの話をしたのでした。

今回はGodExcelオブジェクトを完成させていきます。

その前に、彼(彼女?)の現在の姿を確認しておきましょう。

'GodExcel.cls
Option Explicit

'プロパティ
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

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"

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

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

ワークシートはこんな作りでした。 f:id:shinmai_papa:20190804163940p:plain

GodExcelオブジェクトの問題点

このオブジェクトの責任は、神エクセルの情報を正しく保持することです。

その視点から見たとき、このオブジェクトの状態は責任を全うできるでしょうか。

残念ながらこのオブジェクトは神エクセルの情報を正しく保持できない可能性があります。

それは、このオブジェクトの各プロパティの値は外部から変更が可能だからです。

外部のプログラムからプロパティの値を変更されては、責任を全うすることができません。

ではどうすればいいでしょうか。

とても簡単な話で、外部からプロパティを変更できないようにしてあげればいいのです。

外部からプロパティを変更できないようにする

プロパティへのアクセスは、Property LetやProperty Getステートメントとしてクラスモジュールに定義していました。

外部からプロパティを変更できないようにするためには、Property Letステートメントを削除します。

せっかく追加したのに・・・(-_-;)

いえいえ、本当は最初からオブジェクトの設計がうまくできればいいのですが、最初からそんなうまくいくはずありません。

試行錯誤の繰り返しです。

徐々に慣れていけばいいのです。


わざわざクラスモジュールにプロパティの設定や取得まで定義するクラスモジュールのメリットがこんなところに生きてきました。

GetやLetステートメントを使って、オブジェクトの特性に合わせてプロパティへのアクセスを柔軟に制御することができるのです。

オブジェクトのプロパティの設定はClass_Inititalizeサブプロシージャで行い、プロパティへのアクセスはGetのみとする。

これでGodExcelオブジェクトは「神エクセルの情報を正しく保持する」という責任を全うできるようになりました。

大分、様になってきました、GodExcelオブジェクト。プロパティ周りはこれで完成です。

プロパティ周りが整備されたGodExcelクラスのコード

GodExcelオブジェクトを生成するGodExcelクラスのコードはこうなりました。

GodExcel.cls
'プロパティ
Private pNameFurigana As String
'一部プロパティ省略

Const NAME_FURI_RNG As String = "B6:U6"
'~一部定数省略~

Public Property Get NameFurigana() As String
   NameFurigana = pNameFurigana
End Property

Public Property Get NameKanji() As String
   NameKanji = pNameKanji
End Property

Public Property Get BirthDay() As Date
   BirthDay = pBirthDay
End Property

Public Property Get PostalCode() As String
   PostalCode = pPostalCode
End Property

Public Property Get Address() As String
   Address = pAddress
End Property

Public Property Get MailAddress() As String
   MailAddress = pMailAddress
End Property

Public Property Get WorkPlace() As String
   WorkPlace = pWorkPlace
End Property

Public Property Get Proffsion() As String
   Proffsion = pProffsion
End Property

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

GodExelの利便性をさらに高めるアイディア

クラスモジュールを使ってオブジェクトを生成するメリットは、プロパティを操作することだけではありません。

オブジェクトは、プロパティ以外にメソッドを持つことができます。

メソッドとは、オブジェクトに付随する関数的なものです。

いまいちわかりにくいですね。そんなときは実際の例を見てみましょう。

例えば今回の場合、神エクセルの住所から都道府県名を知りたいときどうすればよいでしょうか。

GodExcelオブジェクトのAddressから、呼び出し元の別のプログラムが求めることもできます。

しかしそれではオブジェクト化したメリットが生かされません。

せっかくオブジェクト化したのですから、GodExcelオブジェクトが都道府県名を教えてくれると、呼び出し元のプログラムはすごく助かります。

このような場合、オブジェクトに都道府県名を教えてくれるメソッドを持たせることを考えます。

色々な想像を働かせ、 こんなメソッドがあったら便利だよね、というものを追加してあげると使い勝手のよいオブジェクトができます。

メソッドはオブジェクトに関係あるものだけ

使い勝手のよいオブジェクトにメソッドは必須なのですが、あれもこれも追加していると何をしたいオブジェクトだかわからなくなってしまいます。

「オブジェクトの責任は何か」を考えて、適当なメソッドを追加してあげます。

GodExcelオブジェクトの責任は「神エクセルの情報を保持すること」です。神エクセルの情報についての便利なメソッドを追加してあげるとよいかと思います。

例としてこんなメソッドが考えられます。

  • 住所の都道府県名を返すメソッド
  • 氏名の苗字と名前を返すメソッド

などなど。

GodExcelオブジェクトのように、シートの情報をオブジェクト化する場合のメソッドは、シートの情報に関係するものがほとんどです。

それを意識すれば、責任の範囲から外れることはないかと思います。

次回でGodExcelオブジェクトが一応完成

9回目にしてやっと、メソッドの話が出てきました・・・。

長かった・・・。

このシリーズも佳境ですね。

次回は、メソッドをGodExcelオブジェクトに実装し、GodExcelオブジェクトは完成させます。

長かった・・・。

ここまでお読みいただき、ありがとうございました。

www.tekizai.net