参照渡しと値渡し

値を渡す方法は2種類あります。「参照渡し」/「値渡し」といわれる方法です。以下説明していきます。

まず「参照渡し」の例題です。値をセットして呼び出しを行い、呼び出された側は、値を表示したのち、変数の内容を修正します。呼んだ側に戻った時は修正された値が入っています。リスト3をみてください。

[リスト3]参照渡し例題(Sub_rei2.xlsm)

Sub yobu()
    a = 10
    test a  '(1)
    MsgBox a    '結果 50
End Sub
Sub test(ByRef a)  '(2)
    MsgBox a    '結果 10
    a = 50
    MsgBox a    '結果 50
End Sub

yobuメインルーチンで変数aに10をセットし、testを呼びます。「参照渡し」の宣言は(2)のように引数の前にByRefを付けることで行います。testプロシージャで受け取った値を表示したのち、数値を変更します。呼ばれた側に戻ったときは、変数の値は変更されています。次は、「値渡し」の例題です。リスト3と同じ例題を「値渡し」で書いてみました。リスト4をみてください。

[リスト4]値渡し例題(Sub_rei3.xlsm)

Sub yobu()
    a = 10
    test a
    MsgBox a    '結果 10
End Sub

Sub test(ByVal a)
    MsgBox a    '結果 10
    a = 50
    MsgBox a    '結果 50
End Sub

宣言は引数の前にByValを付けることで行います。呼んだ側に戻った時は呼び出した値のままです。 値渡しの場合はメインルーチン側とサブルーチン側と別々の変数を用意します。メインルーチンからサブルーチンを呼ぶ時、メインで作成した変数の値のみをサブルーチンで作成した変数へ渡します。メインへ戻る時は引数の受け渡しは行わないので、サブルーチン側の変数の値を変えてもメインルーチンの変数には反映されません。前記の参照渡しの場合はメインで作成した変数をそのままサブルーチンで使用するので、サブルーチンで値を書きなおすとメインに戻った時は変数の値は変更されています。

「参照渡し」の時は、ByRefを使いました。「値渡し」の時は、ByValを使います。ByRef/ByValどちらも指定しない時はByRefが指定されたものとみなされます。明示的に指定したいときは、ByRef/ByValを付けておくと良いと思います。

「値渡し」はサブルーチンを呼んで引数を渡した時、呼ばれる側が間違って引数の値を修正するような事はないので、それぞれ独立して処理を作成することができます。「参照渡し」は、同じ目的に使用する変数を複数作る必要がなく、効率的です。また、故意に呼んだ側の変数の値を変更したいときなどには、便利です。ただ、きちんとコメントで残しておかないと、後で追加や修正を行う時混乱する元となります。

値を返すプロシージャ

Functionプロシージャを利用することで呼びだし元に処理の結果を戻すことができます。Excelに組み込まれていて、良く使用される関数にsum関数などがありますが、このような定型的な処理を自分で作成できるのが、値を返すプロシージャです。ユーザー定義関数ともいわれます。書き方をリスト5に示します。

[リスト5]Functionプロシージャの書き方

Function 呼び出し名(引数)
  ・・・ここに処理を書きます
  呼び出し名=返す値
End Function

プロシージャに付けた名前に値を設定すると、それが戻り値となります。

メインルーチンからサブルーチンを呼ぶ

Subプロシージャの時と同じように、メインルーチンからFunctionプロシージャを呼んでみましょう。ワークシートの表示は図2と同じものです。リスト6をみてください。

[リスト6]サブルーチンを呼ぶ例題(Function_rei1.xlsm)

Sub Main()
    a = Cells(2, 2)
    b = Zizyou(a)   '(1)
    Cells(4, 2) = b
End Sub
Function Zizyou(b)
    Zizyou = b * b  '(2)
End Function

(1)でサブルーチンを呼んでいます。値を返してくれるので、b=で値を受け取っています。答えの表示はメイン側で行います。Functionプロシージャは(2)で答えを返しています。

Functionプロシージャも引数を使用することができます。引数の書き方はSubプロシージャと同じです。(1)のように、Functionプロシージャを呼ぶ場合は引数は必ずカッコ「()」でくくりましょう。

Functionプロシージャをセルに設定

Subプロシージャの引数がないものが、マクロでした。Functionプロシージャの場合は、「=呼び出し名(引数)」で直接セル上に書くことができます。=sum()などと同じ使い方ができるのです。 セル上に書かれる時、どこに書かれるかわかりません。基本的にFunctionプロシージャのリストの中で、固定セルからデータを取り込んだり、固定セルにデータを書き込んだりはしないほうが良いでしょう。リスト6で作成したFunctionプロシージャをシート上に設定してみましょう。以下の図をみてください。

図3:Functionプロシージャをセルに設定

図3の上の図がリスト6で作成したZizyouをセルに設定しているところです。図3の下の図が、数値を入れて計算させたところです。Functionプロシージャをセルに設定した場合、気をつけなければいけないことがあります。標準で設定されている関数も同じなのですが、一つのExcelファイルの中にたくさんの関数をセットすると、文字を入力して、内容が変わった時、設定してあるすべての関数の再計算を行なうので、非常に時間がかかってしまいます。

ほどほどの数のFunction設定にしておきましょう。マクロの場合はボタンを押すなど、マクロの実行命令が出た時のみしか動作しませんので、上記の心配はなくなります。セル上で変更の度に再計算を行わないようにする設定も用意されています。

図4:再計算の設定

「Officeボタン」-「Excelのオプション」で上記の図が表示されます。「数式」の項目で設定してください。手動にした時は、F9キーで再計算を行います。