VBA技術解説
標準モジュールとシートモジュールの違い

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

標準モジュールとシートモジュールの違い


エクセルVBAを始めたばかりの人に教えるとき、
まずは標準モジュールを挿入して、そこに書きましょう、と教えます。
しかし後で見ると、時に間違ってシートモジュールに書いている場合が結構あります。


そういう時に、必ず聞かれるのが、
「何が違うんですか?」
「どこが違うんですか?」
そういう時は、
「今はその違いについて説明しても混乱するだけですから、とにかく標準モジュールに書いてください。」
このようにお伝えすることが結構あります。

とはいえ、
イベント処理等でシートモジュールを扱うようになったら、その違いは正確に理解しておかなければなりません。
以下では、標準モジュールとブックモジュールとシートモジュールの違いを列挙的に説明します。
用語的には、若干の独自補正を加えています。
なぜなら、正式用語を羅列しても理解しづらく、それで理解できる人にはそもそも説明が不要だからです。

書かれている場所と概要

標準モジュール
ブックに属しています。
ブック内に自由に挿入・削除できます。
いくつでも挿入できますし、無くても構いません。

ブックモジュール
ブックに属しています。
初期名称は「ThisWorkbook」
ブック内に一つだけです。

シートモジュール
シートに属しています。
シートと一対一の関係です。
シートを削除すれば、シートモジュールも削除されてしまいます。


シートモジュールはシートに属しています。
つまり、シートをコピーすれば、シートモジュールも一緒にコピーされます
これを逆手にとって、シートモジュールに意図的に記述することで、他のブックにマクロVBAをコピーすることもできます。

シートを省略してRangeやCellsと記述した時

VBAの書き方として、シート修飾せずに、いきなりRangeやCellsから書き始めた場合。
つまり、
Range("A1") = 1
Cells(2,1) = 2
このように書いた場合です。

標準モジュール
アクティブブックのアクティブシートのセル
ブックモジュール
アクティブブックのアクティブシートのセル
シートモジュール
シートモジュールが記述されているシートのセル

もちろん、ブック・シートで修飾していれば、それらは同じ動作になります。
そして、本来はブック・シートはしっかり指定すべきす。
ThisWorkbook.Worksheets("Sheet1").Range("A1")
つまり、基本通りにブック・シートを指定していれば、この違いはあまり気にする必要はありません。

他モジュールから使う時

Public指定の変数やプロシージャーを他のモジュールで使う時の記述の違いです。
もちろん、Privateは他のモジュールからは使用できません。

標準モジュール
全てのモジュールでそのまま使用可能
Public 変数hoge
これを他のモジュールで使用する時は、
変数hoge
とだけ記述すれば使用できます。

ブックモジュール
常にオブジェクト名で修飾する必要があります。
ThisWorkbookの、
Public 変数hoge
これを他のモジュールで使用する時は、
ThisWorkbook.変数hoge
と記述する必要があります。

シートモジュール
常にオブジェクト名で修飾する必要があります。
Sheet1の、
Public 変数hoge
これを他のモジュールで使用する時は、
Sheet1.変数hoge
と記述する必要があります。

以下も参考してください。
第108回.変数の適用範囲
・プロシージャーレベル変数 ・・・ プロシージャー内でのみ使用可能 ・モジュールレベル変数 ・・・ モジュール内でのみ使用可能 ・パブリック変数 ・・・ 全てのモジュールの全てのプロシージャーで使用可能 ・変数の適用範囲について簡単にまとめてると ・定数(Const)の適用範囲について ・変数の重複について ・変数は、極力狭いスコープで使う事が望ましいとされます。


デバッグ時の違い

ここは、実際のエラーメッセージを見てください。

標準ジュール
マクロ VBA シートモジュール ブックモジュール

このようなダイアログが表示され、「デバッグ」押下で、
VBAの当該行が黄色反転表示されます。

ブックモジュール
シートモジュール
マクロ VBA シートモジュール ブックモジュール

「デバッグ」がなく、当該VBA行が不明です。

上記の動作違いの原因
このような動作違いは、ツールのオプションの設定に依存して起きています。

マクロ VBA シートモジュール ブックモジュール

このエラートラップの指定に依存しています。
初期値の
「エラー処理対象外のエラーで中断」
この状態の時に、上で書いたような違いが発生します。
「クラスモジュールで中断」または「エラー発生時に中断」にしてあれば、
上のエラー時のメッセージでの「デバッグ」押下はどちらも同じになります。

ブック/シートモジュールを使う場合は、「クラスモジュールで中断」にしておいたほうが良いでしょう。

標準モジュールとシートモジュールの使い分け方

標準モジュールは名前の通りですと、標準的に使うモジュールということになりますが、
そもそも標準と言う言葉があまりにも曖昧に感じられて混乱しやすいのだと思います。

シートやブックはオブジェクトと呼ばれます。
そのオブジェクトに付帯しているモジュールなので、オブジェクトモジュールという言い方もします。

オブジェクトモジュール(ブックモジュール/シートモジュール)
・オブジェクトと切り離すことのできない処理
・一緒にしておいた方が良い処理
オブジェクトモジュールには、これらの処理を記述します。
代表的なものが、イベントプロシージャーになります。
イベントプロシージャーは、当該オブジェクトのモジュールに書かなければならず、オブジェクトと切り離すことのできない処理になります。

単にシートに「依存する処理」という考え方をしてしまうと、
多くの処理がシートに依存していることになり、やたらとシートモジュールに書くことになってしまいます。
そもそも、ほとんどはブックに依存しているので、全てブックモジュールに書くことになってしまいますよね。
つまり、
オブジェクトと一体としてそこに無ければならない処理なのかが判断基準になってくるでしょう。
簡単に考えるなら、シートをコピーした時を想定してみると良いでしょう。
シートをコピーすれば、シートモジュールもコピーされます。
例えば、イベント処理として、

Sheet1
Private Sub Worksheet_Change(ByVal Target As Range)
  '・・・
  'いろいろな処理
  '・・・
End Sub

このSheet1をコピーしてSheet2を作成した時、このシートモジュールも全てコピーされます。
上記のイベント処理も当然コピーされますが、それはむしろ都合が良いでしょう。
しかし、
「いろいろな処理」この記述も含めてそれぞれのシートに存在することになります。
この「いろいろな処理」が数十行のVBAで書かれていたとしたらどうでしょうか。
いったんは問題ないでしょうが、何かの変更が発生したら、、、
ではどうしたら良いか。
「いろいろな処理」の部分は標準モジュールに記載して、
イベントプロシージャーからはCallするような作りにしておくことを考えるべくでしょう。
(当然Tagetを直接または加工して引数として渡すことになります。)

イベント処理以外でもシートモジュールを使用することはあるでしょう。
この時にも、シートのコピーは常に念頭に置いて考えるべきです。
もちろん、
シートをコピーすることが無いといった場合や、
それぞれのシートにVBAが存在している事の是非については、
個別の判断が必要になることは言うまでもありません。

標準モジュール
・オブジェクトとは切り離しておいた方が良い処理
・複数オブジェクトから汎用的に使用される処理
上記以外でも、オブジェクトモジュールに記載する処理以外は全てここに書きます。


ここは見解がいろいろありそうですが、
イベント処理を覚えるまでは、まずは標準モジュールだけ使う事をお勧めしておきます。

シートモジュールの便利な活用方法はありますが、
それらは、イベント処理くらいまで習得した後に考えれば良いと思います。



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

Rangeオブジェクト.Valueの省略について
シート保護でユーザー操作を制限する
シートに数式を設定する時のセル参照の指定方法
標準モジュールとシートモジュールの違い
オートフィルタ(AutoFilter)の使い方まとめ
複雑な条件(複数除外等)のオートフィルター(AutoFilter)
クリップボードを使わないセルのCopy
Rangeの使い方:最終行まで選択を例に
フルパスをディレクトリ、ファイル名、拡張子に分ける
Colorプロパティの設定値一覧(カラー定数、XlRgbColor列挙)
VBAを定型文で覚えよう


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

数字(1~50)を丸付き数字に変換するVBA|VBA技術解説(2022-11-15)
TEXTAFTER関数(テキストの指定文字列より後ろの部分を返す)|エクセル入門(2022-11-14)
TEXTBEFORE関数(テキストの指定文字列より前の部分を返す)|エクセル入門(2022-11-14)
TEXTSPLIT関数(列と行の区切り記号で文字列を分割)|エクセル入門(2022-11-12)
LAMBDA以降の新関数はVBAで使えるか|VBA技術解説(2022-11-11)
WRAPCOLS関数(1次元配列を指定数の列で折り返す)|エクセル入門(2022-11-08)
WRAPROWS関数(1次元配列を指定数の行で折り返す)|エクセル入門(2022-11-08)
EXPAND関数(配列を指定された行と列に拡張する)|エクセル入門(2022-11-07)
TAKE関数(配列の先頭/末尾から指定行/列数を取得)|エクセル入門(2022-11-06)
DROP関数(配列の先頭/末尾から指定行/列数を除外)|エクセル入門(2022-11-06)


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

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.マクロって何?VBAって何?|VBA入門
10.ExcelマクロVBAの基礎を学習する方法|エクセルの神髄




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


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



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