こんにちは。業務自動化の世界へようこそ。
「マクロの記録」でコードを書き出し、少しずつ自由に動かせるようになったあなたへ。次に立ちはだかる壁は、「なぜか変数の値が勝手に変わっている」という怪奇現象ではないでしょうか。
そのバグ、実はVBAの引数の渡し方、`ByRef`と`ByVal`を理解することで根絶できます。これを知ることは、単なる文法知識を超えて「プログラムのデータ管理」という設計思想に触れるということです。
さあ、VBAの深淵を少しだけ覗いてみましょう。
—
1. そもそも「引数」を渡すとはどういうことか?
関数(SubやFunction)にデータを渡すとき、私たちは「値そのもの」を渡しているつもりになりがちです。しかし、VBAのデフォルト設定では「そのデータが入っている住所(メモリ上の場所)」を渡しています。
これが `ByRef`(バイ・レフ:参照渡し) です。
一方で、`ByVal`(バイ・バル:値渡し) は、そのデータの「コピー」を渡します。
図解的イメージ
- ByRef(参照渡し): 共有フォルダにある書類を直接編集してもらう。相手が書き込めば、元の書類も変わる。
- ByVal(値渡し): 書類のコピーを渡す。相手が何を書こうが、あなたの手元の原本は汚れない。
—
2. なぜ `ByRef` がバグの温床になるのか
VBAの恐ろしい仕様は、何も書かないとデフォルトで `ByRef` になる点です。つまり、あなたが意識せずに関数を呼び出すたびに、元の変数が「書き換えられるリスク」を抱えているのです。
以下のコードを見てください。
Sub Main()
Dim myScore As Long
myScore = 80
‘ 関数を呼び出す
CalculateBonus myScore
‘ ここで myScore はどうなっているか?
MsgBox “最終スコア: ” & myScore
End Sub
‘ ByRef(省略時)で受け取ると…
Sub CalculateBonus(ByRef score As Long)
‘ 内部で勝手に値を書き換えてしまう
score = score + 20
End Sub
この結果、`myScore` は `100` になります。もしあなたが「元々のスコアは80のまま、計算結果だけを知りたかった」のであれば、これは致命的なバグの始まりです。
—
3. 「意図しない書き換え」を防ぐための鉄則
バグを生まないエンジニアは、「デフォルトを信用しない」という原則を徹底しています。
鉄則:原則 `ByVal`、必要なら `ByRef`
基本的には、引数はすべて `ByVal` で渡す習慣をつけてください。関数の中で変数を書き換える必要があると確信した時だけ、明示的に `ByRef` と書くのです。
‘ 安全な設計:コピーを渡すので、元の値は絶対に守られる
Sub CalculateBonusSafe(ByVal score As Long)
Dim finalScore As Long
finalScore = score + 20
MsgBox “計算後の値は ” & finalScore & ” ですが、元データは汚しません。”
End Sub
—
4. 現場で役立つ「使い分け」の判断基準
初学者のうちは、以下のガイドラインに従うだけでコードの品質が劇的に変わります。
- `ByVal` を選ぶべき場面(9割がこれ):
- 計算結果だけを出したいとき
- 文字列や数値を関数に渡して加工したいとき
- 「元の値は変えたくない」という安心感が欲しいとき
- `ByRef` を選ぶべき場面(1割の例外):
- オブジェクト(RangeやWorksheetなど)を操作するとき
- 一つの関数で複数の値を同時に変更・返却したいとき(上級者向けの手法)
—
まとめ:あなたのコードを「堅牢」にするために
プログラミングにおいて、「自分の予期しないタイミングでデータが変わる」ことほど怖いものはありません。
1. 省略しない: `Sub Test(ByVal val As Long)` のように、必ず明示的に書く。
2. 守りを固める: 基本は `ByVal`。変数のコピーを渡して、原本を保護する。
3. 意識を持つ: 渡しているのは「値」なのか「住所」なのか、常に想像する。
この感覚を掴めば、あなたはもう「マクロの記録」を卒業したエンジニアの入り口に立っています。VBAは、こうした小さな設計の積み重ねで、驚くほど安定した自動化ツールへと進化します。
ぜひ、今書いているコードの引数に `ByVal` を付けてみてください。それだけで、あなたのコードの「格」が一つ上がりますよ。応援しています。
