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

ExcelマクロVBAの問題点と解決策、VBAの技術的解説
最終更新日:2020-09-29

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


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


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

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

オブジェクトとは

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

オブジェクト指向とは

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

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

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

カプセル化

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

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

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

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

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

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

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

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


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

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

クラスの必要性と利点

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

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

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

クラスがどうしても必要になる処理としては、
RaiseEventで、自作のイベント処理を作るような場合ですと、クラスが良いのですが、
これとて、他の方法で実装できるものがほとんどになるはずです。
RaiseEventの説明は割愛します、興味のある方は別途調べて下さい。
・Eventステートメント ・RaiseEventステートメント ・WithEventsキーワード ・標準モジュールと動作概要 ・ユーザーフォーム(UserForm1) ・クラス(clsEvent) ・クラスを使ったイベントの解説 ・VBAクラスを使ったイベントの最後に

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

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

以下は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回.エクセルの言葉を理解する(オブジェクト、プロパティ、メソッド)
・VBAが表示するメッセージ ・オブジェクトとは ・プロパティとは ・メソッドとは ・プロパティとメソッドの違い ・オブジェクトの階層(親子構造) ・エクセルの言葉であるVBAを日本語に翻訳する ・最終行取得のコードを訳してみる ・VBA用語を覚えることについて ・ExcelマクロVBA入門等の対応ページ
このページくらいは理解していることとして説明をしていきます。

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

オプションの変更

初期設定では、クラス内でエラー発生してもクラス内のエラー行でVBEは停止せず、呼び出し元の行で停止します。
クラス内のエラー行で停止する設定に変更します。
詳細は、VBEの使い方:ツールのオプション設定を参照してください。
・「メニュー」→「ツール」→「オプション」 ・編集 ・エディターの設定 ・全般 ・ドッキング ・ツールのオプション設定の最後に

「メニュー」→「ツール」→「オプション」
「全般」タブ→「エラートラップ」
クラス モジュールで中断を選択しておいてください。
エラー発生時に中断
On Errorにかかわらず、エラー発生時に中断します。
全てのモジュールが対象になります。
クラス モジュールで中断
ハンドルされない(On Errorがない)エラーがクラス モジュールで発生すると、エラーが発生したコード行でプロジェクトがブレーク モードに入ります。
エラー処理対象外のエラーで中断
エラー処理対象外とは、具体的にはOn Error対象外という事です。

クラス モジュールの挿入

メニューの「挿入」→「クラス モジュール」
ショートカットは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のみの読み取り専用プロパティということです。

Propertyプロシージャの詳細については以下を参照してください。
第140回.Property {Get|Let|Set} ステートメント|VBA入門
・そもそもプロパティとは ・VBAでプロパティを作成するステートメント ・Property {Get|Let|Set} ステートメントの構文 ・Propertyプロシージャの使用例 ・Propertyプロシージャの実践例

メソッドの作成

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クラスの完成コード ・全体の機能と構成 ・クラスで、列名の入力支援と列移動対応するための手順 ・作成済のクラス(clsColumn)をエクスポートして雛形にする ・シートの列タイトルからクラスファイル(.cls)を出力 ・クラスファイル(.cls)のインポート ・全てを連続実行できるように変更 ・列番号のプロパティを自動作成するVBAの完成コード ・最後に
VBAクラスの作り方:独自Rangeっぽいものを作ってみた
・クラスの全VBAコード ・サンプルとして使うブックの構成 ・標準モジュールでの使い方 ・最後に
クラスを使って他ブックのイベントを補足する
・WithEventsキーワード ・全体の機能と構成 ・VBAコード ・VBAコードの解説 ・標準モジュールでのクラスの使い方 ・アプリケーションのイベント一覧と調べ方 ・最後に
クラスとイベントとマルチプロセス並列処理
・クラスとイベントとマルチプロセス並列処理の概要 ・VBAの全コード ・まとめと感想 ・最後に
クラスとCallByNameとポリモーフィズム(多態性)
・CallByName関数 ・クラスとCallByNameとポリモーフィズム(多態性)のVBAコード ・オブジェクト(クラス)も動的に変更すると ・最後に
オートフィルタを退避回復するVBAクラス
・オートフィルターに関するページ ・オートフィルターを退避回復するVBAクラスの概要 ・オートフィルターを退避し回復するクラスのVBAコード ・クラスを利用する標準モジュールのVBAコード ・処理の要点と解説 ・最後に
オートフィルタ退避回復クラスを複数シート対応させるVBAクラス
・オートフィルタ退避回復クラスを複数シート対応させるVBAクラスのコード ・クラスを利用する標準モジュールのVBAコード ・最後に
コレクション(Collection)の並べ替え(Sort)に対応するクラス
・コレクション(Collection)の並べ替え(Sort)に対応する方法 ・コレクションの並べ替えに対応するクラスのVBAコード ・コレクションの並べ替えに対応するクラスの使い方 ・コレクションの並べ替えに対応するクラスの実行時間 ・最後に
VBAクラスのAttributeについて(既定メンバーとFor…Each)
・VBAクラスのエクスポートとインポート ・Attribute VB_PredeclaredId ・Attribute VB_Exposed ・Attribute [procName.]VB_Description ・Attribute variableName.VB_VarUserMemId ・Attribute procName.VB_UserMemId = 0 ・Attribute procName.VB_UserMemId = -4 ・VBAクラスのAttributeの最後に
VBAクラスを使ったイベント作成(Event,RaiseEvent,WithEvents)
・Eventステートメント ・RaiseEventステートメント ・WithEventsキーワード ・標準モジュールと動作概要 ・ユーザーフォーム(UserForm1) ・クラス(clsEvent) ・クラスを使ったイベントの解説 ・VBAクラスを使ったイベントの最後に
コントロールの動的作成|ユーザーフォーム入門
・コントロールの動的作成の動作説明 ・コントロールの表示/非表示を切り替える ・動的に部品コントロールを追加/削除する ・コントロールの動的作成の最後に
イベントプロシージャーの共通化|ユーザーフォーム入門
・サンプルのユーザーフォーム ・イベントプロシージャーの共通化のVBA ・イベントプロシージャーの共通化の問題点 ・イベントプロシージャーの共通化の雛形VBA ・イベントプロシージャーの共通化の最後に
SQL入門:DB接続部分をクラスで作成しています
・DBとはSQLとは ・SQL入門の目次 ・SQLを使った既存サンプル



同じテーマ「VBAクラス入門」の記事

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


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

構成比を合計しても100%にならないと言われた…|ツイッター出題回答 (2022-09-01)
一覧から複数条件(部分一致、範囲)に合致するデータを抽出する|ツイッター出題回答 (2022-08-30)
縦横スピルしないXLOOKUP代替(MATCH+INDEX,FILTER,CHOOSEROWS)|エクセル入門(2022-08-27)
IF関数の論理式で比較演算子を省略したCOUNT系関数を書くのは|ツイッター出題回答 (2022-08-23)
LAMBDA以降の新関数の使用例|エクセル入門(2022-08-22)
数珠順列(配置に条件付き)を全て出力する|ツイッター出題回答 (2022-08-20)
日付時刻のマイナス表示に対応する方法|ツイッター出題回答 (2022-08-17)
LAMBDA以降の新関数について|エクセル入門(2022-08-16)
条件付きの最大値と中央値("A"が2文字の条件)|ツイッター出題回答 (2022-08-14)
VBAマクロと操作対象データの分離について|ツイッター出題回答 (2022-08-11)


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

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.繰り返し処理(For Next)|VBA入門
5.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
6.Excelショートカットキー一覧|Excelリファレンス
7.並べ替え(Sort)|VBA入門
8.マクロって何?VBAって何?|VBA入門
9.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
10.エクセルVBAでのシート指定方法|VBA技術解説




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


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



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