【Excel VBA入門】マクロをパーツ化!Subプロシージャを分割して使う方法

【Excel VBA入門】マクロをパーツ化!Subプロシージャを分割して使う方法

ITを使った業務効率化の相談ができるコミュニティ「業務自動化推進ラボ」を公開しました。

こんにちは、業務自動化ツール開発担当の吉池(@valmore_myoshi)です。

VBAを書いていたら思いのほか長くなってしまったことありませんか?管理しづらいと感じたらマクロを分割するタイミングです!

一連のコードはSubプロシージャごとに分割でき、他のプロシージャも呼び出せます。本記事では、Callを使った他プロシージャの呼び出し方法や引数付きのSubプロシージャを作る方法を解説します。

Callステートメントで他のプロシージャを呼び出す

プロシージャはコードのまとまりです。VBAでいえばSub ~ End Subで囲まれたSubプロシージャを思い浮かべてもらうとわかりやすいかと思います。

このSubプロシージャですが、Callステートメントを使うことで他のSubプロシージャを呼び出せます。例えば下記のコードはmacro1からmacro2を呼び出しています。結果を見ると「マクロ1を実行します。」の次に「マクロ3を実行します。」と表示されており、macro1の途中でmacro2が実行されたことがわかります。

  1. Sub macro1()
  2. Debug.Print "マクロ1を実行します。"
  3. Call macro2
  4. Debug.Print "マクロ2を実行します。"
  5. End Sub
  6. Sub macro2()
  7. Debug.Print "マクロ3を実行します。"
  8. End Sub
Sub macro1()
    Debug.Print "マクロ1を実行します。"
    
    Call macro2
    
    Debug.Print "マクロ2を実行します。"
End Sub

Sub macro2()
    Debug.Print "マクロ3を実行します。"
End Sub
Callステートメントサンプル
実行結果

Subプロシージャに引数を設定する

他のプロシージャを呼び出すときに引数を設定することも可能です。プロシージャ名に続けて変数名データ型を入力します。呼び出すときは指定したデータ型に対応した引数を指定します。

  1. Sub macro1()
  2. Debug.Print "マクロ1を実行します。"
  3. Call macro2("マクロ3を実行します。")
  4. Debug.Print "マクロ2を実行します。"
  5. End Sub
  6. Sub macro2(message As String)
  7. Debug.Print message
  8. End Sub
Sub macro1()
    Debug.Print "マクロ1を実行します。"
    
    Call macro2("マクロ3を実行します。")
    
    Debug.Print "マクロ2を実行します。"
End Sub

Sub macro2(message As String)
    Debug.Print message
End Sub

Optionalキーワードで引数を省略可能にする

引数の前にOptionalキーワードを指定し、デフォルト値を指定すると省略可能な引数を設定できます。基本的にはデフォルト値だけど、状況によっては引数を設定したいといったときに便利です。

  1. Sub macro1()
  2. Call macro2
  3. Call macro2(0.1)
  4. End Sub
  5. Sub macro2(Optional tax As Double = 0.08)
  6. Debug.Print "税率は" & tax * 100 & "%です。"
  7. End Sub
Sub macro1()
    Call macro2
    
    Call macro2(0.1)
End Sub

Sub macro2(Optional tax As Double = 0.08)
    Debug.Print "税率は" & tax * 100 & "%です。"
End Sub
実行結果

参照渡しと値渡し

引数の渡し方には参照渡し値渡しの2種類あります。参照渡しは引数に変数を指定するときに、呼び出し先でも同じ実体を参照する方法です。渡された引数に変更があると、呼び出し元にも反映されます

一方、値渡しは単純に値のコピーが引数として渡されます。呼び出し先で変更があっても、呼び出し元には反映されません

ByRefキーワードで参照渡し

参照渡しするには、ByRefキーワードを使います。呼び出し先の引数名の前にByRefキーワードを付けるだけです。下記例では、最初に変数taxに0.08を代入していますが、macro2に参照渡しし、0.1を代入されています。そのため、呼び出し元にも反映され、結果的に変数taxには0.1が入っています。

  1. Sub macro1()
  2. Dim tax As Double
  3. tax = 0.08
  4. Debug.Print "税率は" & tax * 100 & "%です。"
  5. Call macro2(tax)
  6. Debug.Print "税率は" & tax * 100 & "%です。"
  7. End Sub
  8. Sub macro2(ByRef tax As Double)
  9. tax = 0.1
  10. End Sub
Sub macro1()
    Dim tax As Double
    
    tax = 0.08
    
    Debug.Print "税率は" & tax * 100 & "%です。"

    Call macro2(tax)
    
    Debug.Print "税率は" & tax * 100 & "%です。"
End Sub

Sub macro2(ByRef tax As Double)
    tax = 0.1
End Sub
実行結果

ByValキーワードで値渡し

呼び出し先の引数名の前にByValキーワードを付ければ値渡しになります。下記例は、参照渡しのサンプルを値渡しに変えただけですが、結果である変数の値は変わってません。これは、macro2を呼び出すときに渡した引数が変数taxの値のコピーだからです。

  1. Sub macro1()
  2. Dim tax As Double
  3. tax = 0.08
  4. Debug.Print "税率は" & tax * 100 & "%です。"
  5. Call macro2(tax)
  6. Debug.Print "税率は" & tax * 100 & "%です。"
  7. End Sub
  8. Sub macro2(ByVal tax As Double)
  9. tax = 0.1
  10. End Sub
Sub macro1()
    Dim tax As Double
    
    tax = 0.08
    
    Debug.Print "税率は" & tax * 100 & "%です。"

    Call macro2(tax)
    
    Debug.Print "税率は" & tax * 100 & "%です。"
End Sub

Sub macro2(ByVal tax As Double)
    tax = 0.1
End Sub

まとめ

分割したSubプロシージャを呼び出す方法や引数設定について解説しました。処理が複雑になればなるほどVBAのコード量も増えてきます。一つのSubプロシージャにまとめるのではなく、コードの見通しが良くなるように分割しましょう。

引数を渡すときも参照渡しと値渡しの2種類あります。呼び出し先でも引数に渡した変数と同じ実体を参照したい時は参照渡し、その必要がなければ値渡しにして使い分けましょう。

SubプロシージャのほかにもFunctionプロシージャを使ったユーザー定義関数は戻り値を指定できます。ユーザー定義関数に興味がある方はこちらをご覧ください。
【Excel VBA入門】ユーザー定義関数の作り方。Functionプロシージャを理解する