忍者ブログ
バイオインフォマティックス技術者試験、情報処理試験など、IT系の試験を基礎から勉強します。また、Javaなどプログラミングを勉強します。

【VBAスタンダード対策】変数の運命を分ける「値渡し」と「参照渡し」を攻略!

【VBAスタンダード対策】変数の運命を分ける「値渡し」と「参照渡し」を攻略!

プロシージャに引数を渡す際、VBAには「変数のコピーを渡す方法」と「変数そのものの場所を教える方法」の2通りがあります。呼び出された側で値を書き換えたとき、呼び出し元の「元の変数」に影響が出るかどうかが最大の構造的違いです。

1. 問題:引数の受け渡しによる「元の値」の変化

【 問題 】 プロシージャ Main から Process を呼び出しました。Process 内で引数の値を書き換えた後、再び Main に戻ってメッセージを表示した際、**元の変数 num が書き換わってしまう(10から20に変わる)**のは、どのような受け渡し構造のときでしょうか?

Sub Main()
    Dim num As Integer : num = 10
    Call Process(num)         ' --- ここで呼び出し ---
    MsgBox num               ' --- 元の変数はどうなった? ---
End Sub

Sub Process(n As Integer)
    n = 20                   ' --- 呼び出された先で書き換え ---
End Sub

① 値渡し(ByVal):変数の「分身(コピー)」を渡している場合
② 参照渡し(ByRef):変数の「実体(メモリ上の住所)」を教えている場合
③ 直接渡し:変数をそのまま移動させている場合
④ 共有渡し:すべての変数をモジュールレベルで共有している場合

2. 正解:引数の受け渡し概念に関する正解

正解: ② 参照渡し(ByRef):変数の「実体」を教えている場合

3. 解説:データの「コピー」か「実体」か

引数の受け渡しには、構造的に「分身を渡す」のか「本物を共有する」のかという違いがあります。VBAの既定(デフォルト)は参照渡しであるため、意識せずに書くと呼び出し元の値が書き換わってしまう可能性があります。

[ データの受け渡し構造図 ]

■ 値渡し (ByVal = By Value)
[Main] num(10) --(コピーを送信)--> [Process] n(10)
[Process]で n=20 にしても、[Main]の num(10) は変化なし

■ 参照渡し (ByRef = By Reference)
[Main] num(10) --(住所を共有)--> [Process] n(←実体はnum)
[Process]で n=20 にすると、[Main]の num(10) も 20 に変わる

[ なぜこの違いが重要なのか ]
ByVal(値渡し):元のデータを壊したくない、安全に処理したい時に使います(使い捨てのコピー)。
ByRef(参照渡し):呼び出し先に複数の結果を書き込んでもらいたい時や、巨大なデータを効率よく扱いたい時に使います。

1. ここが試験に出る!: スタンダード試験では、コードの実行結果として「最後に表示される変数の値」を問う問題が頻出します。宣言部に ByVal があるかないかを見極め、呼び出し元の変数が「守られているか、書き換わっているか」を判定できるかが勝負の分かれ目です。
2. エンジニアの視点: Java 17などのオブジェクト型引数は、実質的に「参照の値渡し」という少し複雑な挙動をしますが、VBAの ByRef はもっと直接的な「変数そのもの」の共有です。不慮の書き換えバグを防ぐために、実務では「原則 ByVal で書き、理由がある時だけ ByRef を使う」のが理系NEOな堅牢な設計ですね。


4. まとめ

「分身のByVal、実体のByRef」。この概念を理解すれば、複雑なプロシージャ連携でもデータの流れを完全に見失わずに済みます。減数分裂が元の情報を維持しながら新しい細胞を作るように、VBAも適切な受け渡し構造を選ぶことで、データの正確性を保ちながら処理を繋いでいくのです。


PR

【VBAスタンダード対策】値を呼び出し元へ届ける「Functionの戻り値」を攻略!

Functionプロシージャの最大の特徴は、計算や加工の結果を「戻り値(返り値)」として呼び出し元に渡せることです。VBAでは、他の言語のような Return キーワードではなく、独自の代入構造を持っています。

1. 問題:戻り値を設定する正確な構文

【 問題 】 引数で受け取った数値 num を2倍にして呼び出し元に返す、Functionプロシージャ「DoubleValue」を作成したい。空欄 ( A ) に入る正確なコードはどれでしょうか?

Function DoubleValue(num As Integer) As Integer
    ( A ) = num * 2
End Function

① Return
② DoubleValue
③ Result
④ Value

2. 正解:戻り値の代入構造に関する正解

正解: ② DoubleValue

3. 解説:なぜ「プロシージャ名」に代入するのか?

VBAのFunctionプロシージャは、宣言した**「プロシージャ名と同名の変数」**が自動的に用意されるような構造になっています。その名前に値を代入することで、End Function に到達したとき、その値が呼び出し元へと持ち帰られます。

[ Functionの戻り値構造図 ]

Sub Main()
  ans = DoubleValue(5)  ← (2) 10を受け取る
End Sub

         ↓ 呼び出し

Function DoubleValue(num)
  DoubleValue = num * 2  ← (1) 自分自身の名前に値を詰める
End Function

[ 他の選択肢が誤りである理由 ]
① Return:Javaなどの他言語で使われる構文であり、VBAではこの構造をサポートしていません。
③・④:これらはただの変数名とみなされます。プロシージャ名と一致しない名前に代入しても、戻り値としては機能しません。

1. ここが試験に出る!: スタンダード試験の穴埋め問題では、この「プロシージャ名をもう一度書く」という構造が正しく理解できているかが問われます。また、宣言の最後にある As Integer(戻り値の型指定)と、実際に代入する値の型が一致しているかどうかも、構造的な正確性を測るポイントとなります。
2. エンジニアの視点: Java 17などの return 文に慣れていると、名前に代入する構造は少し特殊に感じますが、これは古き良きBASIC言語の伝統的な構造です。値を代入した後も、End Function に行くまでは処理を続行できるという特徴がありますが、混乱を避けるために代入後は速やかに終了させるのが「理系NEO」な綺麗な書き方です。


4. まとめ

「Functionは、自分の名前を箱にして値を持ち帰る」。この一風変わった代入構造こそが、VBA関数におけるデータの出口です。減数分裂が正しい情報をセットにして次世代へ運ぶように、VBAも Function 名という器に正確な値を収めることで、プログラム間の完璧なデータリレーを実現するのです。


【VBAスタンダード対策】SubとFunction:役割と呼び出し方の構造を攻略!

SubとFunctionは、どちらも処理をまとめる箱ですが、その「出口(出力)」の構造が決定的に異なります。どのような場面でどちらを選択すべきか、実務的な判断力を確認しましょう。

1. 問題:SubとFunctionの使い分けと構造的制約

【 問題 】 SubプロシージャとFunctionプロシージャの「使い方の違い」に関する記述として、VBAの構造上正しいものはどれでしょうか?

① Subはセル内の数式から直接呼び出して計算結果を返せるが、Functionは呼び出せない。
② Functionは呼び出し元に値を返せるが、Subは呼び出し元に値を返すことができない。
③ どちらも Call キーワードを使って呼び出す際、必ず戻り値を受け取る変数を用意しなければならない。
④ Functionプロシージャ内では、セルの値や書式を変更するなどの「動作」を記述することは一切禁止されている。

2. 正解:プロシージャの運用構造に関する正解

正解: ② Functionは呼び出し元に値を返せるが、Subは呼び出し元に値を返すことができない。

3. 解説:出口(戻り値)があるかないか、それが構造の差

Sub(サブルーチン)は「一連の動作を完遂すること」が目的であり、Function(関数)は「計算した結果を報告すること」が主な目的です。この目的の違いが、呼び出し方の構造に現れます。

[ 実務的な使い分けと呼び出し構造図 ]

■ Subプロシージャ:アクション型
・呼び出し方:Call DoAction または DoAction
・主な役割:転記、書式変更、印刷、ファイル保存など(動き中心)。

■ Functionプロシージャ:データ型
・呼び出し方:ans = GetValue()(変数への代入が基本構造)
・主な役割:複雑な計算、判定(True/False)、文字列加工など(結果中心)。

[ 選択肢の構造的ミス ]
①の誤り:セルから呼び出せる(ユーザー定義関数)のは「値を返す」構造を持つFunctionだけです。
④の誤り:VBAから呼び出す場合は動作可能ですが、セルから呼び出す「ユーザー定義関数」として使う場合に限り、他のセルの値を変更するなどの動作に制約がかかります。

1. ここが試験に出る!: スタンダード試験では「Subは値を返さない」という基本に加え、Functionを呼び出す際に ans = MyFunc() のように戻り値を受け取る構造が正しく書けているかが問われます。また、FunctionをSubのように Call で呼ぶことも可能ですが、その場合は戻り値が捨てられるという特殊な挙動も理解しておく必要があります。
2. エンジニアの視点: Java 17の void メソッドと、戻り値を持つメソッドの使い分けと同じですね。実務では「サイドエフェクト(状態変化)を起こすならSub」「純粋に計算だけして値を返すならFunction」と構造を分離して設計するのが、理系NEOな保守性の高いコードへの近道です。


4. まとめ

「動きを命じるSub、答えを求めるFunction」。この構造的役割の違いを理解することで、マクロの設計は劇的に整理されます。減数分裂が単なる分割ではなく「次世代へ繋ぐ情報の選別(Function的役割)」を伴うように、VBAも適切なプロシージャの選択によって、正確なデータのリレーを実現するのです。

【VBAスタンダード対策】処理を中断する「Exit Sub」の構造を攻略!

Subプロシージャは通常、上から下へと順番に実行されますが、エラー発生時や特定の条件を満たした際に「それ以降の処理を行わずに呼び出し元へ戻る」という制御が必要になります。この「途中で終わる」ための正確な記述を確認しましょう。

1. 問題:プロシージャの中途終了

【 問題 】 以下のコードにおいて、変数 ans が 0 の場合に、メッセージを表示せずにプロシージャを途中で終了させたい。空欄 ( A ) に入る正確な記述はどれでしょうか?

Sub CheckValue(ans As Integer)
    If ans = 0 Then
        ( A )
    End If

    MsgBox "結果は " & ans & " です"
End Sub

① End   ② Exit Sub   ③ Stop   ④ Return Sub

2. 正解:中途終了の構文に関する正解

正解: ② Exit Sub

3. 解説:なぜ「Exit Sub」でなければならないのか?

プロシージャを物理的な終端(End Sub)まで実行させずに、その場で呼び出し元に制御を戻す命令が Exit Sub です。これは「出口を無理やり作る」ような構造的役割を果たします。

[ プロシージャ脱出の構造図 ]

Sub Main()              Sub CheckValue(ans)
  |                        +-------------------+
  +--[ 呼出 ]-----------> | If ans = 0 Then  |
  |                       |   Exit Sub ------|---(即座に復帰)
  +<-[ 復帰 ]------------- | End If           |
  |                       |  [以降の処理]      |
  |                       | End Sub          |
  |                       +-------------------+

[ 注意すべきキーワードの違い ]
Exit Sub:現在のプロシージャのみを終了し、呼び出し元へ戻ります。
End:プログラム全体の実行を完全に停止し、すべての変数をリセットします。影響範囲が大きすぎるため、中途終了には通常使いません。

1. ここが試験に出る!: 試験では「このコードを実行した際、MsgBoxが表示されるか否か」を問う形式で出題されます。If 文の条件が成立し、Exit Sub を踏んだ時点で、その下のコードは一行も実行されないという構造的遮断を正しく読み解く必要があります。
2. エンジニアの視点: Java 17などの return; ステートメントに相当します。異常な値を最初にはじく「ガード句」として Exit Sub を活用することで、後続のメインロジックをシンプルに保つことができ、保守性の高い「いけいけ」なコード構造が実現します。


4. まとめ

「異常があれば Exit Sub で即脱出」。この中途終了の構造を使いこなすことで、予期せぬエラーや不要な処理の実行を防ぐことができます。減数分裂が特定のチェックポイントで制御されるように、VBAも Exit Sub という関門を設けることで、確実かつ安全なプログラム制御が可能になるのです。



【VBAスタンダード対策】処理を繋ぐ「プロシージャ呼び出し」を攻略!

一つの大きな処理(Main)から、特定の役割を持つ別の処理(Sub)を実行することを「呼び出し」と言います。VBAでは、Callキーワードを使う方法と、省略する方法の2通りがありますが、それぞれ記述の「構造」が異なります。

1. 問題:他のSubプロシージャを呼び出す正確な記述

【 問題 】 引数 val を受け取るSubプロシージャ Update を呼び出す際、VBAの構文(フォーマット)として不適切なものはどれでしょうか?

Sub Main()
    Dim val As Integer : val = 100
    ' --- ここで Update を呼び出す ---
End Sub

Sub Update(n As Integer)
    MsgBox n
End Sub

① Call Update(val)
② Update val
③ Call Update val
④ Update(val) (※引数が1つの場合、動作はするが非推奨の構造)

2. 正解:呼び出しの構造(Callとカッコの有無)に関する正解

正解: ③ Call Update val

3. 解説:呼び出しによって「制御」が移る構造

VBAでは、別のSubを呼ぶ際に「Callを使うならカッコで囲む」「Callを使わないならスペースで繋ぐ」という鉄則があります。どちらの方法でも正しく呼び出せますが、記述を混ぜることはできません。

[ プロシージャ呼び出しの構造図 ]

Mainプロシージャ              Updateプロシージャ
+-------------------+          +-------------------+
| Sub Main()        |          | Sub Update(n)    |
|  [処理1]          |          |                  |
|  Call Update(v) --|---(呼出)--->  [引数nの処理]    |
|  [処理2] <--------|---(復帰)---  End Sub          |
| End Sub           |          +-------------------+
+-------------------+

[ 2通りの正しいフォーマット ]
パターA(Callあり):Call Update(val)
パターB(Callなし):Update val
※ Callを使うと「今から別のSubを呼び出す」という意図が明確になり、構造が分かりやすくなります。

1. ここが試験に出る!: 試験では「Callを書かずにカッコを付ける」という誤用が狙われます。特に引数が2つ以上ある場合(例:Call Calc(a, b))において、Callを抜いて Calc(a, b) と書くと構文エラーになります。この「連動性」を正確に把握しましょう。
2. エンジニアの視点: Java 17などモダンな言語では常にカッコが必要ですが、VBAは「文(Statement)」として呼び出す形式を継承しています。大規模な開発では、後から見た人が「どこで外部Subへ飛んでいるか」を一目で判断できるよう、Callを明示的に付ける構造が推奨されることが多いです。


4. まとめ

「Callを使うならカッコ、使わないならスペース」。この呼び出し構造をマスターすることで、複雑に絡み合うマクロの動きを正確に制御できるようになります。減数分裂において情報がリレーされるように、VBAも正確な呼び出しによって、一つの大きな目的(業務自動化)を達成するのです。