パソコン活用研究5番街(Visual Basic、Excel(VBA)、BASIC プログラミング研究)

                 vb&vba−変数のスコープ

昔の手続き型BasicからVBに移行して、とまどう問題のひとつに変数のスコープがあります。
VBで初めてプログラムを作る時、この問題でエラーの発生や、思った通りプログラムが動かない
といったことを経験することが多いのではないかと思います。
スコープ?何だソリャという感じかもしれませんが、簡単に言うとその変数が有効なのはどの
範囲かと言う事です。(ちっとも言ってる意味がわからない?すぐに慣れると思います。)

例えば、変数X,Yの値を交換するプログラム(すなわちSWAP)を考えてみます。
昔の手続き型Basicなら以下のようになります。

10 x=0: y=5    '初期値として X=0,Y=5
20 temp=x
30 x=y
40 y=temp
50 print "x=";x
60 print "y=";y

これを実行すると、X,Yの値が交換され、X=5,Y=0と表示されます。
昔のBasicにはローカル変数、グローバル変数といった区別がない(全てグローバルと
考えて良い)ため、変数のスコープといったことにまったく気を使わず、プログラムして
いました。

VB(Qbasicも同様)、VBAでは、変数がプログラムのどの範囲で有効かを示すスコープという
概念があります。VB、VBAでは以下の3つのスコープがあります。

@ローカルスコープ(ローカル変数)
プローシジャ内で宣言された変数で、プロシージャ内でのみ有効です。プロシージャの
終わりで、変数は破壊されます。そのプロシージャ内でのみ有効なので、同じ変数名を
他のプロシージャでローカル変数として使うことができます。

Aモジュールスコープ
VBではそのモジュールのGENERAL部の宣言部でDim,Privateで宣言された変数。
EXCELではモジュールシートのプロシージャ外で、Dim,Privateで宣言された変数。
そのモジュール内のすべてのプロシージャで共通に使えます。ただし、他のモジュールからは
使えません。

Bグローバルスコープ
VBではモジュールのGENERAL部の宣言部でPublicで宣言された変数。
EXCELではモジュールシートのプロシージャ外でPublic宣言された変数。
当該のモジュールだけでなく、他のモジュールからも使えます。
ただし、Visual Basicで他のモジュールから使うには以下のように変数を記述します。
変数が宣言されているモジュール名.変数
例えば、Form1でPublic宣言されたXという変数を、他のモジュール(Form2など)
から使う時は、Form1.Xと記述します。

1 Visual Basicの場合
以下でスコープに気をつけねばならないプログラム例を示します。
先述と同じX,Yの値を交換するプログラムです。
「SWAP」コマンドボタンをクリックするとX,Yの値を交換します。

Swap1プログラム
CommandボタンClickプロシージャ内でX,Yをローカル変数として宣言したもの

'FORMのプロパティ
VERSION 4.00
Begin VB.Form Form1
BackColor = &H00FFFFFF&
Caption = "SWAP"
ClientHeight = 1650
ClientLeft = 1140
ClientTop = 1515
ClientWidth = 4080
FillColor = &H00FFFFFF&
FillStyle = 0 '塗りつぶし
FontTransparent = 0 'False
ForeColor = &H00000000&
Height = 2055
Left = 1080
LinkTopic = "Form1"
ScaleHeight = 1650
ScaleWidth = 4080
Top = 1170
Width = 4200

'Commandボタンのプロパティ
Begin VB.CommandButton Command1
Caption = "SWAP X,Y"
Height = 375
Left = 360
TabIndex = 0
Top = 1200
Width = 1815
End
End
Attribute VB_Name = "Form1"
Attribute VB_Creatable = False
Attribute VB_Exposed = False

'以下がコード部分
Private Sub Form_Load() 
x= 0: y = 5          'フォームのロードにX=0,Y=5を初期値として代入
End Sub
Private Sub Command1_Click()     
Dim x As Integer, y As Integer     'ローカル変数として宣言
temp = x         'X  ,Yの値の交換
x = y
y = temp
Form1.Print "x="; x; " : y="; y
End Sub
SWAP1プログラムの実行結果
X,Yはローカル変数のため、Form1_load()内のx,y とCommand_click()内の
X,Yはまったく互いに独立した変数となっている。フォームのロード時にX=0,
Y=5と初期設定しても、 Command1_click()プロシージャ内では宣言時に0クリア
され、X,Y共に常に0になっている。

SWAP2
GENERAL部の宣言部でPrivate宣言し、X,Yをモジュル変数とした場合

' (宣言部) X,Yをモジュール変数として宣言
private x as integer, y as integer

Private Sub Form_Load()
x= 0: y = 5 'フォームのロードにX=0,Y=5を初期値として代入
End Sub

Private Sub Command1_Click()     
temp = x         'X  ,Yの値の交換
x = y
y = temp
Form1.Print "x="; x; " : y="; y
End Sub
SWAP2の実行結果

「SWAP」コマンドボタンをクリックするたびにX,Yの値が交換されている。
X,Yはモージュール変数となり、モジュール内で共通になったからである。

変数の宣言をきちんとしないとSWAP1の例のように、あれ!X,Yの値が交換されない!
といったミスがおこります。


2 EXCELの場合
EXCELのVBAの場合もVBと同様です。下記の表を見てください。

Module1 Module2
Dim a as integer          
Private b as long
Public s as string

Sub proc1()
Dim d as integer

{変数a,b,s,dが有効}

End Sub

Sub proc2()

{変数a,b,sが有効}


End Sub
Sub proc3()         

{変数sが有効}

End Sub

変数dはProc1()のローカル変数なのでProc1()の中でのみ有効です。
変数a,bは
モジュール変数なので、module1の中のProc1(),Proc2()で有効です。
変数sは
パブリック(グローバル)変数なので、全プロシジャで有効です。

TopPage > Visual BasIc&Excel活用研究目次