プロシージャの種類
VBAには、サブプロシージャ(Sub)とファンクションプロシージャ(Function)の2つの主要なプロシージャの種類があります。サブプロシージャは通常、引数が設定可能で特定のタスクを実行するために使用されます。Excelではマクロとして認識されますが、値を返すことはできません。
一方、ファンクションプロシージャは引数を設定して値を返すことができるため、計算を渡したり値の取得などの用途に適しています。また、マクロとしては認識されないためサブプロシージャから呼び出しを行わなくては利用できません。
プロシージャの種類 | 値を返すか | マクロとして識別されるか | 引数は設定できるか |
---|---|---|---|
サブプロシージャ | 返さない | される | できる |
ファンクションプロシージャ | 返す | されない | できる |
今回は、それぞれのプロシージャの機能と実装方法について説明します。
引数の渡し方(値渡しと参照渡し)
プロシージャには引数を渡すことができます。
渡した引数を利用して、計算・変数の反映・値を返すなどの処理を行うことができます。
値渡し(byVal)
値渡し(ByVal)は、引数の値をコピーして渡す方法です。値渡しでは、呼び出し元の変数の値が変更されても、元の変数には影響を与えません。渡された引数は、新たな変数として扱われます。これは、関数の引数を値渡しで受け取る場合や、サブプロシージャで引数を変更したくない場合に適しています。
以下は値渡しの例です。
Sub ValuePassingExample()
Dim x As Integer
x = 10
' サブプロシージャに値渡しによって変数を渡す
Call ModifyValue(x)
' xの値は変更されない
MsgBox "値渡しの結果:" & x
End Sub
Sub ModifyValue(ByVal num As Integer)
num = num + 5
End Sub
この例では、ModifyValue
サブプロシージャに変数x
を値渡しで渡しています。ModifyValue
内で引数num
を変更しても、元の変数x
には影響を与えません。そのため、メッセージボックスに表示されるx
の値は変更されずに10のままです。
参照渡し(byRef)
参照渡し(ByRef)は、引数のアドレス(参照)を渡す方法です。参照渡しでは、呼び出し元の変数のアドレスが渡されるため、呼び出されたプロシージャ内で引数を変更すると、元の変数にも変更が反映されます。これは、関数の引数を変更し、その変更を呼び出し元で反映させたい場合や、大きなデータ構造を効率的に処理する場合に適しています。
以下は参照渡しの例です。
Sub ReferencePassingExample()
Dim y As Integer
y = 10
' サブプロシージャに参照渡しによって変数を渡す
Call ModifyReference(y)
' yの値が変更される
MsgBox "参照渡しの結果:" & y
End Sub
Sub ModifyReference(ByRef num As Integer)
num = num + 5
End Sub
この例では、ModifyReference
サブプロシージャに変数y
を参照渡しで渡しています。ModifyReference
内で引数num
を変更すると、元の変数y
の値も変更されます。そのため、メッセージボックスに表示されるy
の値は変更後の15となります。
引数にオプションを記載しない場合
引数にオプションを指定しない場合、デフォルトでは参照渡しとなります。つまり、引数に指定された変数はそのままの形でプロシージャ内で使用され、値のコピーではなく元の変数への参照が渡されます。参照渡しの利点は、プロシージャ内で引数の値を変更すると、元の変数の値も変更されることです。しかし、注意が必要であり、引数にオプションを指定することで値渡しに切り替えることも可能です。
Sub DefaultArgumentExample()
Dim x As Integer
x = 10
' サブプロシージャに引数を渡す(オプションを指定しない)
Call ModifyDefaultArgument(x)
' xの値が変更される
MsgBox "参照渡し(デフォルト)の結果:" & x
End Sub
Sub ModifyDefaultArgument(num As Integer)
num = num + 5
End Sub
この例では、ModifyDefaultArgument
サブプロシージャに変数x
を引数として渡していますが、オプションを指定せずに引数を定義しています。この場合、デフォルトでは参照渡しが適用されます。
ModifyDefaultArgument
内で引数num
を変更すると、元の変数x
の値も変更されます。そのため、メッセージボックスに表示されるx
の値は変更後の15となります。
引数を使わないで値を共有する方法
引数を利用しない方法としては、モジュールレベルの変数を使う方法があります。
モジュールレベル変数は、VBAモジュール内で宣言され、そのモジュール内の複数のプロシージャで使用される変数です。モジュールレベル変数はグローバルスコープを持ち、モジュール内のどのプロシージャからでもアクセスできます。以下は、モジュールレベル変数を利用する例です。
Option Explicit
Dim counter As Integer ' モジュールレベル変数
Sub ModuleLevelVariableExample()
counter = 0 ' モジュールレベル変数に初期値を設定
' サブプロシージャを3回呼び出してモジュールレベル変数を増やす
IncrementCounter
IncrementCounter
IncrementCounter
' 結果を表示
MsgBox "カウンタの値:" & counter
End Sub
Sub IncrementCounter()
counter = counter + 1 ' モジュールレベル変数を増やす
End Sub
この例では、ModuleLevelVariableExample
サブプロシージャでモジュールレベル変数counter
を初期化し、IncrementCounter
サブプロシージャを3回呼び出してcounter
を増やしています。
IncrementCounter
内でモジュールレベル変数counter
を操作しているため、複数の呼び出しで値が累積されます。最終的にModuleLevelVariableExample
でメッセージボックスに表示される値は3となります。
モジュールレベル変数はモジュール内でのみ有効であり、他のモジュールやワークブック内の他のモジュールからはアクセスできません。ただし、グローバルモジュール(「ThisWorkbook」モジュールや「Sheet」オブジェクトのモジュールなど)に宣言されたモジュールレベル変数は、プロジェクト内の他のモジュールからもアクセスできます。