VBA技術解説
VBAクラス入門:クラスとは?オブジェクト指向とは?

ExcelマクロVBAの問題点と解決策、エクセルVBAの技術的解説
最終更新日:2019-11-25

VBAクラス入門:クラスとは?オブジェクト指向とは?


VBAを覚えて、いろいろ作りながらネットで調べたりしていると、クラスとかオブジェクト指向といった言葉に出くわします。
VBEの「挿入」の一番下にある「クラスモ ジュール」は気になっていたかもしれません。
このクラスモジュールを使ってクラスを作ります。
そして作ったクラスがオブジェクトになります。


いくら言葉を尽くしても、これらクラスやオブジェクト指向を完全に説明しつくすことは難しいでしょう。

これらクラスやオブジェクト指向は、エクセルVBAで作業を自動化する上で特に必須という事はありません。
しかし、そもそもエクセルそのものがオブジェクトの集まりで出来ています。
エクセルのシートもセルもそれらが全てオブジェクトであり、それがクラスであり、オブジェクト指向で作られています。
VBAを理解する上で、クラスの理解やオブジェクト指向の理解は必ず役に立つものです。

オブジェクトとは

操作対象の事ですと説明されたりしますが、
まずは何かの物体、つまりは対象物と理解すれば良いでしょう。
ワークシート、セル、グラフ、これらが全てオブジェクトです。

オブジェクト指向とは

オブジェクト指向とは、オブジェクト同士の相互の作用として、システムの動作をとらえる考え方であり、
対象物を部品を使って組み立てるように表現してプログラミングしていく事になります。

オブジェクト指向における三大要素
・カプセル化 (encapsulation)
・継承 (inheritance)
・多態性 (polymorphism)

このあたりの用語がでてくると、、、
心配はいりません、少なくともVBAでは、継承も多態性も使えないのですから、
(継承としてはインターフェースだけ使えますが、急ぎ覚える必要はないでしょう。)
従って、カプセル化だけを意識すれば良いのです。

カプセル化

カプセル化とは、関連するデータやその操作を一つ(カプセル)にまとめることを言います。
つまり、関連するものを一つのカプセルとしてまとめ、それを使いまわすことになります。

これは概念的なものになりますので、くどくど言葉で説明してもなかなかピンとこないかもしれません。

一番わかりづらいのは、「関連する」というのが抽象的過ぎるということだと思います。
当然、人によって関連の範囲は変わってくることになります。
つまり、人によってクラスの作り方も変わってくるということです。
「自分に関連する人物」というクラスを作るとして、まずデータとしては、
家族、友人、仕事の同僚、学校の同級生、近所の住人・・・
どこまでを想像し、どこまでを一つにまとめるかは、人それぞれ違ってきます。
全部を一つにまとめても良いし、それぞれを別々にまとめても良い。
まとめる範囲が違えば、必要な操作も変わってきます。
どれが適切なのかの正解はないことがほとんどです。
実践の中で、自ら模索し決定していくことになります。

また、カプセル化の重要な要素として、「隠蔽」があります。
必要な情報のみ外部に公開し、不必要なものは非公開として隠蔽するのです。
つまり、透明なカプセルではなく、不透明なカプセルを作るということです。
そして、カプセルの中に入れたり、カプセルの中から取り出したりする場合は、
専用の出入り口(これがプロパティ)を作ります。
その出入口は、入り口専用・出口専用にすることもできます。
カプセルの中を操作できないようにしておき、カプセルの中を操作したいときは、
カプセルについているボタンを押して操作(これがメソッド)できるようにします。

オブジェクト指向とカプセル化とクラス

オブジェクト指向のプログラムを作るにはクラスが必要です。
といいますか、オブジェクト指向で独自オブジェクトを作るためにクラスが存在しています。

少なくともVBAにおいてクラスを使うときに、
最も意識すべきはカプセル化だと言って良いでしょう。

・関連するデータやその操作を一つにまとめる。
・必要な情報のみ外部に公開し、不必要なものは非公開として隠蔽。


一番勘違いしてほしくないのは、
クラスを使えばカプセル化できるわけではないということです。
キャビネットを買ったからと言って事務所が整理されるわけではありません。
一つのキャビネットには関連するものを整理して入れ、扉を閉めておく。
これは人間がやることであり、これをやらなければいみがありません。
キャビネットに適当にものを入れて扉を開けっぱなしでは、単に物の場所を移動しただけです。
そんなことなら、キャビネットは必要ありません。

クラスを使ってカプセル化したオブジェクトを作るということです。

クラスの必要性と利点

クラスを使って、オブジェクト指向を目指すと、
「プログラムの強度や凝集度は高まり、結合度は下がる」
これが利点と言われても、まあ大抵の人は「何それ」ってことになるはずです。

そもそもクラスを使用しないと実現できない処理はありません。


結果としての全体動作だけなら、別の手段で実現可能です。
(細部まで完全に同じ動作になるかは別として)

クラスがどうしても必要になる処理としては、
RaiseEventで、自作のイベント処理を作るような場合ですと、クラスが良いのですが、
これとて、他の方法で実装できるものがほとんどになるはずです。
RaiseEventの説明は割愛します、興味のある方は別途調べて下さい。
VBAクラスを使う事で、ユーザー定義イベントを作成したり、動的にイベントを割り当てる事が出来ます。ユーザー独自のイベントを作成したり、フォームに動的に追加したコントロールにイベントを設定することができます。EventステートメントとRaiseEventステートメントを使う事で、ユーザー定義イベントつまりユーザー独自のイベントを作成できます。

つまり、余程大規模なシステムを作る以外では、
無くてはならないものではなく、使えれば便利なものだということです。
逆の言い方をすれば、
クラスが使いこなせるようになると、これほど便利なものはなく、
もし一切クラスを使わずに作れと言われると困ってしまうくらいの存在となります。

一般的なクラスに関する説明

以下はMicrosoftサイトでの説明文の抜粋を引用しています。
オブジェクトの概要
オブジェクトは、データおよびそのデータを操作するメソッドを含む構造体のことです。
Visual Basicで行うほとんどすべての作業は、オブジェクトにかかわっています
classはある対象の抽象表現であり、オブジェクトはそのクラスを表す実例です。
※ほほ原文のまま

オブジェクトとクラス
Visual Basicの各オブジェクトは、クラスによって定義されます。
クラスは、オブジェクトの変数、プロパティ、プロシージャ、およびイベントを記述します。
オブジェクトはクラスのインスタンスです。
クラスを定義すると、必要な数のオブジェクトを作成できます。
クラスを定義したら、必要な数のオブジェクトを作成することができます。
オブジェクトとそのクラス間の関係を理解するために、クッキーの抜き型とクッキーを考えてみましょう。
クッキーの抜き型はクラスです。
それは、クッキーの特徴 (大きさや形など) を定義します。
クラスを使用して、オブジェクトを作成します。
オブジェクトはクッキーです。
メンバーにアクセスする前に、オブジェクトを作成する必要があります。
※ほほ原文のまま

インスタンスについての補足します
インスタンスとは実体の事です。
クラスはあくまで型であり実態を持っていません。
クラスで作った実体がインスタンスでり、それがオブジェクトです。

短くまとめると、
クラスは型(オブジェクトの設計図)で、型を使って実体化(インスタンス)したものがオブジェクトです。
つまり
オブジェクトとは、クラスのインスタンスであるという事になります。
これがなかなか実感として理解しづらいかもしれません。
あくまでイメージですが、以下のようなとらえ方をしても良いでしょう。

一般名詞と固有名詞、こんな違いとして認識しても良いかもしれません。
一般名詞は特定のものを指しません、物や概念を指すものです。
固有名詞は、特定のものであり、唯一のものです。
つまり、一般名詞は実体を伴わない概念であり、固有名詞は特定の実体を指しています。
クラスは一般名詞で、オブジェクトは固有名詞
漠然とこんな感覚でとらえても良いでしょう。

クラスの比喩的説明

以下では、自動車というクラスを作る場合の例えになります。

自動車クラス
プロロパティ
名前

重量
長さ

ドアの数
排気量

このように、プロパティはオブジェクトの性質を表すデータになります。

Dim 自動車オブジェト As New 自動車クラス
自動車オブジェクトを作るには、自動車クラスのインスタンスを生成することで作成します。

自動車オブジェトのプロパティを設定
自動車オブジェ.名前 = フェラーリ
自動車オブジェ.色 = 赤
自動車オブジェ.重量 = 1.5t
自動車オブジェ.長さ = 3.8m
自動車オブジェ.幅 = 1.9m
自動車オブジェ.ドアの数 = 4
自動車オブジェ.排気量 = 4,000cc

これで上で設定したような仕様の自動車が出来上がるという事です。
出来上がった自動車で、いろいろな事をしていくことになります。

クラスの使い方

作成したクラスを使う時のVBAの具体的な記述について説明します。

「61.FileSystemObjectの使い方」で出てきた
Dim objFSO As FileSystemObject
Set objFSO = New FileSystemObject

FileSystemObject
これがクラスです。

New FileSystemObject
これでインスタンスが作成され、つまりオブジェクトとして使えるようになります。

そして、objFSOがオブジェクトとして使用可能となります。
定義しただけでは、Dim objFSO As FileSystemObject、これだけでは、オブジェクトとして使用できません。
インスタンスを生成して、初めてオブジェクトとして使用できるようになります。

Dim objFSO As New FileSystemObject
これは、型の定義とインスタンスの生成をまとめて行っている事になります。

一般的な書き方をすると
Dim 変数 As クラス名
Set 変数 = New クラス名
または、
Dim 変数 As New クラス名


同じクラスのオブジェクトは、いくつでも作る事が出来ます。
同じクラスから、複数のインスタンスが生成できます。
Dim 変数1 As New クラス名
Dim 変数2 As New クラス名
変数1と変数2は、同じクラスからインスタンス生成した、別々のオブジェクトです。

自動車というクラスをもとに、
セダンやSUVを作り出すという感じで理解すれば良いでしょう。

クラスを体験してみる

いろいろと説明してきましたが、

これらを延々と文章で説明しても、かえって混乱するだけのようにも思えます。
「百聞は一見に如かず、百見は一行にしかず」
とにかく「やってみる」という事も時には重要な事だと思います。

ただし、最低限の知識として、
第12回.エクセルの言葉を理解する(オブジェクト、プロパティ、メソッド)
ExcelマクロVBAを書いて実行すると、何やら難しい日本語らしきメッセージが表示されることがあります、エクセルが何かを伝えようとしている訳ですが、何を言っているのかを理解してあげなければエクセルがかわいそうです。しかし、エクセルが表示するエラーメッセージの言葉の意味位は知っていて損はありません。
このページくらいは理解していることとして説明をしていきます。

では、いよいよ実際にクラスを作っていきましょう。
クラスを作ると言う事は、オブジェクトを作ると言う事です。

クラス モジュールの挿入
メニューの「挿入」→「クラス モジュール」
ショートカットはAlt→I→C

VBA クラス オブジェクト指向

プロジェクトウインドウで右クリックからも挿入できます。

VBA クラス オブジェクト指向

クラス名の変更
プロパティウインドウのオブジェクト名で変更します。

VBA クラス オブジェクト名

プロパティの作成
Property Get
プロパティの値を取得するプロシージャです。
取得とは、クラスを使う側(オブジェクトを使う標準モジールのプロシージャー)から見て取得ということです。
変数 = Range("A1").Value
このValueプロパティがGetです。

Property Let
プロパティの値を設定するプロシージャです。
設定とは、クラスを使う側(オブジェクトを使う標準モジールのプロシージャー)から見て設定ということです。
Range("A1").Value = 100
このValueプロパティがLetです。

Property Set
プロパティのオブジェクトを設定するプロシージャです。
オブジェクトの場合は、Letではなく、Setになります。

GetとLet、または、GetとSetは同一の名前が使えます。
通常は、同一名にして、ペアで作成します。
つまり、値の設定と取得を同じプロパティ名にすることで使いやすくできるという事です。
RangeのValueプロパティには、GetとSetがあるので、設定と取得が同じValueで使えています。

読み取り専用プロパティとは、Getプロパティのみのプロパティになります。
RangeのAddressプロパティは設定できません。
つまりGetのみの読み取り専用プロパティということです。

メソッドの作成
Subステートメント、Functionステートメントで作成します。
標準プロシージャーでの扱いと同様になります。

クラス内にPublicで定義されたSubまたはFunctionは、そのクラスのインスタンスを経由して使用することが出来ます。
つまりPublicは、クラス外から使えるメソッドになります。
Privateで定義されたメソッドは、クラス外から直接使う事はできません。

メソッドは、そのオブジェクトに何らかの動作をさせるものです。
Rangeオブジェクトであれば、
Delete
Insert
AutoFilter
これらのように、そのオブジェクトに何らかの振る舞いをさせるものになります。

クラスの使用例

以下は、独自のワークシートを作るクラスです。
クラスモジュールを挿入し、貼り付けて下さい。

Private pSheet As Worksheet

'扱うシートを設定
Public Property Set MySheet(argSheet As Worksheet)
  Set pSheet = argSheet
End Property
'扱うシートを取得
Public Property Get MySheet() As Worksheet
  Set MySheet = pSheet
End Property

'シート名を変更
Public Property Let Name(ByVal argName As String)
  MySheet.Name = argName
End Property
'シート名を取得
Public Property Get Name() As String
  Name = MySheet.Name
End Property

'セル範囲を(開始セル,行数,列数)で指定できるようにする
Public Property Get MyRange(sRange As Range, ByVal RowSize As Long, ByVal ColumnSize As Long) As Range
  Set MyRange = sRange.Resize(RowSize, ColumnSize)
End Property

'セルを(行位置,列位置)で指定できるようにする
Public Property Get MyCells(ByVal RowIndex As Long, ByVal ColumnIndex As Long) As Range
  Set MyCells = MySheet.Cells(RowIndex, ColumnIndex)
End Property

'指定セルのアクティブセル領域に罫線を引く
Public Sub CurrentBorders(sRange As Range)
  sRange.CurrentRegion.Borders.LineStyle = xlContinuous
End Sub

MySheet
扱うシートを設定・取得できるようにしているプロパティです。
設定するプロパティとして、Property Set
取得するプロパティとして、Property Get
シートはオブジェクトなので、Property Setを使います。

Name
シート名を変更・取得できるようにしているプロパティです。
設定するプロパティとして、Property Let
取得するプロパティとして、Property Get
シート名は単なる値なので、Property Letを使います。

MyRange
セル範囲を(開始セル,行数,列数)で指定できるようにするプロパティです。
Property Getだけなので、読み取り専用プロパティとなっています。

MyCells
セルを(行位置,列位置)で指定できるようにするプロパティです。
Property Getだけなので、読み取り専用プロパティとなっています。

CurrentBorders
指定セルのアクティブセル領域に罫線を引くメソッドです。
戻り値が必要ないので、Subプロシージャーで作成しています。

標準プロシージャーで上のクラスを使う場合です。

Dim myClass As New Class1
Set myClass.MySheet = ActiveSheet
With myClass
  .Name = "クラスTEST"
  .MyCells(2, 1) = 1
  .MyRange(.MyCells(3, 1), 1, 3) = 10
  .CurrentBorders sRange:=.MyCells(2, 1)
End With

クラス入門の最後に

最初は遊びがてら、上記のコードをいじってみるところから初めてみると良いと思います。
いきなり書籍やWEBで、しっかりクラスを理解しようとしてもかなりの苦労が待ち受けているだけだと思います。
標準モジュールでも簡単に実現できるような簡易なコードから使い始めれば良いでしょう。

ただし既に書いている通り、クラスは無くてはならないものではありませんので、
VBAの基本及び応用において、一通り習得できた後にチャレンジしてみるくらいで十分です。

以下はクラスに関する解説およびクラスのVBAサンプルです。
VBAクラスの作り方:列名の入力支援と列移動対応
クラスを使う良さとして、入力支援が使えてコーディングが楽になるという利点があります、列番号をクラスに持てば、列名が候補表示されて非常に便利です。しかし、これを実装するには、かなりの手間がかかります。つまり、クラス作成に手間をかけて、その後を楽にするということになります。
VBAクラスの作り方:列名のプロパティを自動作成する
クラスに列名のプロパティを作成することで、入力支援が使えてコーディングが楽になりますが、列数が多くなればVBAの記述量が増え、コーディングが大変になります。入力支援が使えるのは良いが、その事前準備があまりに大変ではやる気が失せてクラス作るのが面倒になってしまいます。
VBAクラスの作り方:独自Rangeっぽいものを作ってみた
クラスの作成は、標準モジュールで作成していた時とは様相が違い戸惑う部分も多いと思います、それは、初めてVBAに取り組んだ時の戸惑いと同じかもしれません。最初はとにかく慣れることが一番です、細かい文法や機能は、少し慣れてから改めて学んでも遅くはありません。
クラスを使って他ブックのイベントを補足する
VBAでイベントを使う場合は、通常はイベントが発生するオブジェクト(ブックやシート等)のモジュールに記載します、つまり、各ブックの中にマクロを入れなければなりません。他ブックのイベントを処理するには、WithEventsキーワードを付けた変数宣言を使います、クラスを使って他ブックのイベントを補足する方法について具体的なVBAコードで紹介します。
クラスとイベントとマルチプロセス並列処理
エクセルVBAではマルチスレッドによる並列処理はサポートされていません、つまり通常は順序良く直列に処理していくしかありません。しかし処理時間が多大にかかるような処理も現実には存在しているため、エクセルVBAで並列処理したいという要望も出てきます。
クラスとCallByNameとポリモーフィズム(多態性)
VBAの使い方が進んでいくとクラスを使うようになっていきます。クラスを使うようになるとオブジェクト指向という言葉に出会い、オブジェクト指向を学んでいくとポリモーフィズム(多態性)という言葉に出会います。オブジェクト指向における多態性の説明としては、メソッドの呼び出し時に、メソッドが属するオブジェクト(クラス)の種類によって呼び出し先の実装コードが選択され、
オートフィルタを退避回復するVBAクラス
シートにオートフィルタが適用されていて、かつ絞り込みされている場合は、VBAでは、何かと注意が必要になります。このような場合、オートフィルタを解除するか、フィルタ絞り込みをクリアして対応している事が多くなります。しかし、オートフィルタを解除したり、フィルタをクリアしてしまうと、それまでの絞り込み条件が消えてしまい、
オートフィルタ退避回復クラスを複数シート対応させるVBAクラス
シートにオートフィルタが適用されていて、かつ絞り込みされている場合は、VBAは何かと面倒になります。そこで、これに対応するために作成したものが、オートフィルタを退避回復するVBAクラス ただし、これはシートが一つしか扱えません。複数シートで使う場合は、シートごとにクラスのインスタンスを作成する必要があります。
コレクション(Collection)の並べ替え(Sort)に対応するクラス
オブジェクトを扱う事が多くなってくるとコレクション(Collectionオブジェクト)を使う機会も増えてくると思います。配列やディクショナリー(Dictionary)を使ったほうが良い場合も多くはありますが、単純にオブジェクトを保管し、順序通り(FIFO)に処理するだけなら、とても扱いやすい場合もあります。
VBAクラスのAttributeについて(既定メンバーとFor…Each)
VBAクラスをエクスポートすると各種のAttributeが設定されているのが確認できます。それぞれのAttributeの意味と、さらに追加で指定できるAttributeについて説明します。Attributeの変更はVBA標準でサポートされておらず、その使用については慎重であるべきですが、どのようなものがあるかを知るのは、



同じテーマ「VBA技術解説」の記事

VBAクラス入門:クラスとは?オブジェクト指向とは?
クラスを使って他ブックのイベントを補足する
VBAクラスの作り方:列名の入力支援と列移動対応
VBAクラスの作り方:列名のプロパティを自動作成する
VBAクラスの作り方:独自Rangeっぽいものを作ってみた
クラスとイベントとマルチプロセス並列処理
クラスとCallByNameとポリモーフィズム(多態性)
オートフィルタを退避回復するVBAクラス
オートフィルタ退避回復クラスを複数シート対応させるVBAクラス
コレクション(Collection)の並べ替え(Sort)に対応するクラス
VBAクラスのAttributeについて(既定メンバーとFor Each)


新着記事NEW ・・・新着記事一覧を見る

SQL関数と演算子|SQL入門(12月1日)
データの取得:集約集計、並べ替え(DISTINKT,GROUP BY,ORDER BY)|SQL入門(11月30日)
データの取得:条件指定(SELECT,WHERE)|SQL入門(11月29日)
データの挿入:バルクインサート|SQL入門(11月28日)
データの挿入(INSERT)と全削除|SQL入門(11月26日)
テーブル名変更と列追加(ALTER TABLE)とテーブル自動作成|SQL入門(11月25日)
テーブルの作成/削除(CREATE TABLE,DROP TABLE)|SQL入門(11月24日)
データベースに接続/切断|SQL入門(11月23日)
SQLiteのインストール|SQL入門(11月22日)
SQL入門:VBAでデータベースを使う|エクセルの神髄(11月22日)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
3.RangeとCellsの使い方|VBA入門
4.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
5.変数宣言のDimとデータ型|VBA入門
6.繰り返し処理(For Next)|VBA入門
7.マクロって何?VBAって何?|VBA入門
8.セルに文字を入れるとは(Range,Value)|VBA入門
9.空白セルを正しく判定する方法(IsEmpty,IsError,HasFormula)|VBA技術解説
10.ひらがな⇔カタカナの変換|エクセル基本操作



  • >
  • >
  • >
  • VBAクラス入門:クラスとは?オブジェクト指向とは?

  • このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


    記述には細心の注意をしたつもりですが、
    間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
    掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
    掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



    このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
    本文下部へ