適材適所

パソコン作業の自動化・効率化のための情報を発信するブログ(VBA,PowerShellなど)

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

この記事では

  • VBAのクラスモジュールの使い方を解説しています。
  • クラスモジュールを理解するためのオブジェクト指向について解説しています。
  • この記事はクラスモジュールの実践的な使い方を学びたい人に向けて書いています。
  • シリーズものです。その1はこちら→挫折した人のためのVBAクラスモジュール入門_その1 - 適材適所

おさらい

その1では題材のエクセルから情報を取得するコードを書いて、あーじゃないこーじゃないとうんちくを語りまくったのでした。もう少しオブジェクト指向についての「うんちく」にお付き合いください。

シートの情報をオブジェクト化する、ということをしつこいくらい言っております。 今回はこのオブジェクト化というところに焦点を当てていきたいと思います。

※過去、オブジェクトについて学習して挫折した人は、その時のことはいったん忘れてください。オブジェクトにはプロパティがあって、メソッドがあって・・・という説明はあくまで形式的な話です。ここで話すのは、オブジェクトとは何ぞやという話です。

シートの情報をオブジェクト化する

前回、オブジェクト化とは、「意味のある形にする」と説明しました。意味のある形とはなんでしょうか。前回のコードを例にとってみてみましょう。

Option Explicit

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 example1()
   Debug.Print getItem(Range(NAME_FURI_RNG))
   Debug.Print getItem(Range(NAME_KAN_RNG))
   Debug.Print getItem(Range(BIRTH_Y_RNG))
   Debug.Print getItem(Range(BIRTH_Y_RNG))
   Debug.Print getItem(Range(BIRTH_D_RNG))
   Debug.Print getItem(Range(POST1_RNG))
   Debug.Print getItem(Range(POST2_RNG))
   Debug.Print getItem(Range(ADR_RNG))
   Debug.Print getItem(Range(MAIL_RNG))
   Debug.Print getItem(Range(WORK_PLACE_RNG))
   Debug.Print getItem(Range(PROFFESION_RNG))
End Sub

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
 Debug.Print getItem(Range(NAME_FURI_RNG))

これは氏名のフリガナの文字列を取得しているところです。NAME_FURI_RNGというのはセルのアドレスを表した文字列です。Range(NAME_FURI_RNG)でセルを表しています。getItem関数は引数のセル内の文字列をまとめて返す関数です。結果、氏名フリガナの文字列が取得できています。

確かにこれで文字列は取得できおり、必要な機能を満たしています。

視点を変えてみる

ここでちょっと視点を変えてみてください。今説明した機能を呼び出しているのは誰でしょうか。おそらくメインモジュールか分割されたサブプロシージャということになるでしょう。

どちらにしてもそれは、メインプログラムのフローに内在することになります。メインプログラムのフローに内在するとは何を意味するでしょうか。メインプログラムに責任を持つのはプログラマーです。

つまり何が言いたいかというと、この、氏名フリガナを取得するためのgetItem(Range(NAME_FURI_RNG))に責任を持つのはプログラマーということです。

プログラマーは、適切なタイミングでgetItem関数を呼び出し、引数にNAME_FURI_RNGをアドレスに持つRange型のデータを記述し、氏名フリガナを取得するのです。

対して、もしシートの情報がオブジェクト化されていたらどうなるでしょうか。

ここでいうオブジェクトとはどんなオブジェクト、つまり「意味のあるもの」かというと、氏名フリガナ、氏名漢字、生年月日、郵便番号、住所、メールアドレス、勤務先名称、職業というデータをもったものです。この意味のあるもの、つまり、オブジェクトに対して、氏名フリガナを聞くと、氏名フリガナを教えてくれる。

これが情報をオブジェクト化するということです。これは何を意味するのでしょうか。これは、情報についての責任をオブジェクトに移管しているということです。プログラマーはオブジェクトに対して欲しい情報を問い合わせるだけで済みます。

いったん立ち止まって考える

話が抽象的になってきました。いったん立ち止まり、最初の例とオブジェクトについてまとめてみましょう。  情報の構造  最初の例=情報に構造はない、表面上の文字列を取得しているだけ  オブジェクト=情報が構造化された状態、意味のある形    責任の所在  最初の例=責任はプログラマー、プログラマーが適切に関数を呼び出して取得する  オブジェクト=責任はオブジェクト、情報を聞くと教えてくれる   情報の構造を見ると、最初の例には構造がないことは明らかです。ただ定数と関数を使ってシート上の文字列を取得しているに過ぎません。ではオブジェクトになるとどうでしょうか。オブジェクトの中には「氏名フリガナ」や「生年月日」といった情報が保持されています。

責任の所在はどうでしょうか。最初の例では氏名フリガナを取得するために関数と定数を使ってメインプログラムもしくはサブルーチンが呼び出します。つまり責任は全てプログラマーにあります。

対してオブジェクトは、オブジェクトに対して、「あなたの氏名フリガナを教えてください」と聞くと氏名フリガナを教えてくれます。

これは責任がプログラマーからオブジェクトに移管された状態です。プログラマーはメインプログラムの作成に注力でき、シートの細かい情報(書式や情報の分割など)について注意を払う必要がなくなるのです。

オブジェクト化することでプログラマー楽になる・・・かもしれない

ながながとうんちくを語ってきました。まとめると、シートの情報をオブジェクト化すると、シートの情報が構造化され、シートの情報の取得が単純化され、書式や情報の分割などの細かいことからプログラマーが解放されるということです。

夢のような話ですね。でも実際はケースバイケースです。オブジェクトを作る作業にもそれなりにコストがかかります。でも大抵は楽になると思います。また、ソースコードの可読性もあがること請け合いでしょう。

話が長くなってしまいました。しかも今回はだいぶ抽象的な話ばかりでした。 全然具体的な話がなくて、すいません<m(__)m> でもこれで「オブジェクト指向」的な話は終わりです。 次回はもっとシートの情報を実際にオブジェクト化し、クラスモジュールについて、具体例を見ていきたいと思います。

www.tekizai.net