1. はじめに
ARアドバンストテクノロジ株式会社(ARI)の鈴木タクヤです。
猫って、いいですよね(唐突)。
最近帰省して実家の猫と触れ合ってきました。無理矢理だっこして引っ掻かれたりもしたけれど、私はげんきです。
さて、今回はExcelフィルタリングツールのソースコード解説第5回です。
(ツールの詳細については以下の記事を、「Excelフィルタリングツール解説シリーズ」タグの記事一覧については以下の記事下部「5. 解説記事のリンク」をご参照ください。)
解説第4回 は変数についての記事でしたが、今回のテーマはその有効範囲「スコープ」です。
2. 変数の「スコープ」とは
変数は一度宣言しておけば使いたいときに使えて便利ですが、どこでも使えるわけではありません。変数の有効範囲を スコープ と呼びます。
2-1 変数のスコープの例
以下はメッセージボックスで変数の内容を表示する例です。
'Subプロシージャa1
Sub a1()
Dim x As String 'String型(文字列)用の変数 x を宣言
x = "猫って、いいですよね。" '変数 x に文字列を代入
MsgBox x '変数 x の内容をメッセージボックスに表示する
End Sub
例①では Subプロシージャ1 a1
の中で変数 x
に値を設定し、x
を 引数2 としてMsgBox関数を呼んでいます。このa1
を実行すると・・・
↑こうなります。変数 x
に文字列"猫って、いいですよね。"
が代入されたことが分かります。
次は少し変えてみます。
'Subプロシージャa2
Sub a2()
Dim x As String 'String型(文字列)用の変数 x を宣言
x = "猫って、いいですよね。" '変数 x に文字列を代入
Call b2 'プロシージャ b2 を呼ぶ
End Sub
'Subプロシージャb2
Sub b2()
MsgBox x '変数 x の内容をメッセージボックスに表示する
End Sub
例②では2つのSubプロシージャが登場しますが、プロシージャa2
は変数x
に値を設定し、プロシージャb2
を呼びます。呼ばれたb2
はx
を引数としてMsgBox関数を呼んでいます。このa2
を実行すると・・・
↑こうなります。"猫って、いいですよね。"
が表示されません。
実は プロシージャ内で宣言した変数は、そのプロシージャ内でしか使用できません。 このとき 「変数のスコープは宣言されたプロシージャ内のみ」 と言えます。
例②ではb2
の中で変数x
を宣言・代入していないため、MsgBox関数で値を表示しようとしている変数x
は、"猫って、いいですよね。"
が代入されたx
とは別の変数とみなされてしまいます。よってメッセージボックスは空(Empty)の表示になります。
スコープから少しでも外れると使えなくなる感じ、飼い猫が家の外で飼い主に呼ばれても知らんぷりするのと似ています(?)
あるプロシージャで宣言した変数の値を別のプロシージャに受け渡したい場合には、以下の例③のように引数として渡す必要があります。
'Subプロシージャa3
Sub a3()
Dim x As String 'String型(文字列)用の変数 x を宣言
x = "猫って、いいですよね!" '変数 x に文字列を代入
Call b3(x) 'x を引数としてプロシージャ b3 を呼ぶ
End Sub
'Subプロシージャb3
Sub b3(ByVal y As String) '👈引数をString型で指定
MsgBox y '👈引数として渡された文字列をメッセージボックスに表示する
End Sub
(例③のb3
に登場するy
はx
に置き換え可能ですが、a3
のx
とは別物であることを強調するためにy
としています。このy
に"猫って、いいですよね!"
が渡されます。 ByVal については 解説第3回 をご参照ください。)
このa3
を実行すると・・・
↑こうなります。(おわかりいただけただろうか…)
VBAのコードの先頭に「Option Explicit」の記載がある場合には変数の宣言が強制されるため、例②のa2
を実行するとb2
側で「変数x
が宣言されてないよ!」とコンパイルエラー3になります。
2-2 モジュールレベル変数
上では「プロシージャ内で宣言した変数は、そのプロシージャ内でしか使用できません。」と書きましたが、最初のSubまたはFunctionより前(「宣言セクション」と呼びます)で宣言した変数は、その モジュール4 全体で使用できます。このような変数を モジュールレベル変数 と呼びます。
Dim x As String '👈String型(文字列)用の変数 x をモジュールレベル変数として宣言
'Subプロシージャa4
Sub a4()
x = "猫って、いいですよね!!" '変数 x に文字列を代入
Call b4 'プロシージャ b4 を呼ぶ
End Sub
'Subプロシージャb4
Sub b4()
MsgBox x '変数 x の内容をメッセージボックスに表示する
End Sub
例④ではDim x As String
の記述をSub a4()
より前で宣言しています。このa4
またはb4
を実行すると・・・
↑こうなります。x
はa4
の中で値を代入されb4
の中で使用されています。つまりx
のスコープはa4
とb4
を含むモジュール全体であることが分かります。
ちなみにオス猫は複数のメス猫の縄張りを囲むようにして自分の縄張りを決めるとか。モジュールレベル変数のスコープは、オス猫の縄張りみたいなものですね(?)
Excelフィルタリングツールでも、モジュールレベル変数を使用しています。
'このツールの設定値を代入する変数の定義
Dim modeNo As Integer 'マクロの起動モード設定用(0:表見出しのコピー, 1:フィルタリング, 2:フィルタのクリア)
Dim settingSheetName As String 'フィルタ条件等を記載する本ツールの設定用シート名
(中略)
Dim targetBook As Workbook 'フィルタ対象ブック
'■共通処理(複数のマクロから呼ばれる)
Sub exeCommonProc() '👈最初のSub
'処理高速化のおまじない
With Applicatio
(後略)
最初に登場するSubプロシージャexeCommonProc
より前で宣言した変数は、複数のSub/Functionプロシージャで使用しています。(多分。)
予期せぬ変数の値の書き換えバグを防ぐためにも、変数はなるべく狭いスコープで使用 することをオススメします。そう、できれば猫の額ほどの。
3. おわりに
以上、変数のスコープについての解説でした。
悪ノリの猫まみれな記事となりましたが、猫アレルギーの方には申し訳ございません。
次回は、Ifステートメントについて解説します。
👇次回
4. おまけ;アクセス修飾子
Excelフィルタリングツールでは使用していませんが、変数のスコープに関蓮する アクセス修飾子 というものがあります。大規模開発などでは必須ですが、個人的なツールの作成などでは必要に迫られないと思うので、アクセス修飾子を2種類だけ紹介します。
アクセス修飾子は変数以外に使用することもありますが、本記事では変数に絞って紹介します。
4-1 Public
モジュールレベル変数の宣言におけるDim
を Public
に書き換えると、さらにスコープが広がり、他のモジュールでも使用できるようになります。
Public x As String
Sub a()
(以下略)
4-2 Private
モジュールレベル変数の宣言におけるDim
を Private
に書き換えても、Dim
と同様にそのモジュール内のどこでも使える変数となります。Public
とは異なり、他のモジュールでは使用できません。
ただし、Dim
とは異なり Private
はプロシージャ内では使用できません。
他のプログラミング言語ではDim
より Private
の方がよく使用されます。
Private x As String '👈Dim x As String と同じ意味
Sub a()
Private x As String '👈プロシージャ内ではコンパイルエラー
End Sub
5. 参考文献
こちらはMicrosoftの公式ドキュメントです。
こちらは私がものすごくお世話になっている「エクセルの神髄」という解説サイト。より深く学習を進めたい方は是非。
猫の縄張りについて。