この記事を読んでわかること
- VBAでのCallの使い方・書き方がわかる
- 別のプロシージャに変数を受け渡しする方法がわかる
- Callを使用した場合によくあるエラーと対処法を知れる
※わかりやすさを重視しております。厳密には解釈が異なる場合がありますことをご了承ください。
-著者情報-
名前:Utatane
VBA(マクロ)歴:3年
Excel使用歴:15年以上
ひとこと:初心者だった当時に戻った気持ちになって解説いたします
VBA(Excelマクロ)でのCallの使い方
まずはCallとは何なのか?Callの役割について見ていきましょう。
Callとは?
Callは、別のサブプロシージャ(Sub ○○)を呼び出して実行するためのステートメントです。
ステートメントとは、命令や宣言を行うための構文です。
「今から特別な処理を始めますよ!」という宣言だと思ってください。
「選手宣誓」や「○○を始めます!」といった感じでしょうか。
VBAで代表されるステートメントには、変数の宣言を行う「Dim」やループ文を管理する「For」、サブプロシージャの始まりとなる「Sub」などがあります。
マクロのプログラムが複雑になると、複数のサブプロシージャ(Sub)に分けて整理することで、可読性が向上します。
しかしながらその場合、サブプロシージャを呼び出す処理が必要になってきます。
その際に使える命令の1つが「Call」ステートメントです。

簡単に言えば、電話で家族におつかいを頼むようなものでしょうか。

ではまず、Callステートメントの基本構文から見ていきましょう。
Callの基本構文
Callの基本構文は以下のとおりです。
▼基本構文
Call サブプロシージャ名
▼使用例1
Call 名前を表示
では始めに、Callの簡単な使い方から学んでいきましょう。
Callの簡単な使い方
前提知識{マクロの基礎・作り方から実行まで}
前提知識{「Debug.Print」で値を表示させる方法}
下記のVBAコードを見てください。
Sub Main()
Call 名前を表示
End Sub
Sub 名前を表示()
Debug.Print "私の名前は Utatane"
End Sub
1~3行目がメインプロシージャ、
5~7行目が名前を表示するサブプロシージャです。
メインの中の6行目でCallを使用しています。
これで「名前を表示」プロシージャが呼び出され、実行されます。
結果、イミディエイトウィンドウに名前が表示され、プログラム終了となります。

引数を指定・戻り値を受け取る
前提知識{変数の宣言や使い方}
Callで呼び出した別のプロシージャに値を渡すこともできます。
前項では、サブプロシージャである「名前を表示」が、「Utatane」という名前を名乗るだけでした。
今回はメインプロシージャの指示に従い、名前を変えられるようにしてみます。
下記のVBAコードを見てください。
Sub Main()
Call 名前を表示("Utatane")
End Sub
Sub 名前を表示(name As String)
Debug.Print "私の名前は " & name
End Sub
前項との違いは、2行目と5行目の()内に値が入ったのと、6行目の「Utatane」が変数に変わったことです。
まずは2行目ですが、()内に値を書くことで、その値を呼び出したプロシージャ(今回は「名前を表示」)に渡すことができます。
この値を引数(引き渡す数)といいます。
5行目でサブプロシージャが値を受け取ります。
今回の「Utatane」は変数「name」に入ります。
あとは変数を表示させるだけです。

変数の受け渡し
前項では値である「Utatane」を引数として受け渡ししました。
今回は「Utatane」が入った変数を受け渡ししてみましょう。
下記のVBAコードを見てください。
Sub Main()
Dim name As String
name = "Utatane"
Call 名前を表示(name)
End Sub
Sub 名前を表示(ByVal name As String)
Debug.Print "私の名前は " & name
End Sub
メインで作成した変数「name」に値(Utatane)を入れ、サブプロシージャに渡します。
サブプロシージャは変数の値を受け取り、表示するという流れで結果は前項と同じです。

7行目の「ByVal」は何なのかというと、値のみの受け渡しを意味します。
「ByVal(値受け渡し)」と「ByRef(参照受け渡し)」
- ByVal:変数内の値だけ受け渡し(元の変数は影響しない)
- ByRef:変数ごと受け渡し(変数内の値を変更すると、元の変数の値も変わる)
前項の例ではわかりにくいので、下記VBAコードを見てください。
▼ByValの例
Sub Main()
Dim i As Integer
i = 1
Call 計算(i)
Debug.Print "iは " & i ' iは1と表示される
End Sub
Sub 計算(ByVal i As Integer) ' 値のみ受け渡し
i = i + 1 ' i = 2(Mainの変数「i」は変わらない)
End Sub
▼ByRefの例
Sub Main()
Dim i As Integer
i = 1
Call 計算(i)
Debug.Print "iは " & i ' iは2と表示される
End Sub
Sub 計算(ByRef i As Integer) ' 変数ごと受け渡し
i = i + 1 ' i = 2(元の変数「i」も変わる)
End Sub
どちらも変数を計算プロシージャに渡して計算させた例です。
7行目の()内が「ByVal」か「ByRef」かだけの違いです。
メインプロシージャの変数「i」を計算プロシージャが受け取り、計算して2になります。
値受け渡しした前者(ByVal)はメインの変数には影響を与えず1のままです。
しかしながら、変数ごと受け渡しした後者(ByRef)はメインの変数も2に変更されてしまいます。
別のモジュールから呼び出す
別モジュールのプロシージャを呼び出すことも可能です。
'Module1
Sub Main()
Dim name As String
name = "Utatane"
Call 名前を表示(name)
End Sub
'Module2
Sub 名前を表示(ByVal name As String)
Debug.Print "私の名前は " & name
End Sub

しかしながら、プロシージャが「Private Sub ○○」となっている場合は呼び出すことができません。
「Private」と「Public」
- Sub、Public Sub:他のモジュールからでも呼び出せる
- Private Sub:宣言されたモジュール内でのみ使用可能
Privateは自分ん家や市町村限定、Publicは全国や全世界とするとわかりやすいかと思います。
Callを省略
実は「Call」を省略してサブプロシージャを呼び出すこともできます。
しかしながら、「Call」をつける場合とつけない場合とで構文が変わる場合がありますので注意しましょう。
▼引数なしの例
▼Callをつけた場合
Sub Main()
Call 名前を表示
End Sub
▼Callを省略した場合
Sub Main()
名前を表示
End Sub
▼引数ありの例
▼Callをつけた場合
Sub Main()
Call 名前を表示("Utatane")
End Sub
▼Callを省略した場合
Sub Main()
名前を表示 "Utatane" ' ()はつけない
End Sub
▼変数を受け渡した例
▼Callをつけた場合
Sub Main()
Dim name As String
name = "Utatane"
Call 名前を表示(name)
End Sub
▼Callを省略した場合
Sub Main()
Dim name As String
name = "Utatane"
名前を表示 name ' ()はつけない
End Sub
Callを省略しても「ByVal(値受け渡し)」や「ByRef(参照受け渡し)」が可能です。
パッと見てわかりやすいのは「Call」をつけた構文です。
しかしながら、「Call」を省略した方が簡潔な構文になりますので、自分や周りのレベルに合わせて使い分けてください。
Shell関数との違い
「Call」とよく似たものに「Shell」関数があります。
主な違いは以下のとおりです。
Call | Shell | |
主な用途 | VBA内のプロシージャを呼び出す | 外部プログラムやコマンドを実行する |
対象 | VBA内のSub | Windowsの実行ファイル(.exe、.batなど) |
構文 | Call プロシージャ名 (Callは省略可) | Shell “プログラム名”, ウインドウ状態 |
戻り値 | なし(Sub実行) | プロセスID(Long型)またはエラー |
同期/非同期 | 同期 (順番通り実行される) | 非同期 (外部プログラムが終了するのを待たない) |
「Call」はプロシージャを呼び出すのに対し、「Shell」は外部プログラムを実行する場合に使われます。
よくあるエラーと対処法
ここからは、Callを扱う上でよく発生するエラーを紹介いたします。
SubまたはFunctionが定義されていません

呼び出すSubやfunctionが存在しなかったり、名前を間違えている可能性があります。
コードを再度確認しましょう。
また、別のモジュールにあるPrivateプロシージャを呼び出すとこのエラーが発生します。
差し支えなければ「Public」に変更するか、同一モジュール内に移動することで、エラーを回避できます。
引数は省略できません

受け取り側(サブプロシージャ)が2つの引数を要求しているのに対し、引き渡し側(メイン)が1つしか渡していない場合などに発生します。
Sub Main()
Call 名前を表示("Utatane") ' 名前の他に職業を渡す必要がある
End Sub
Sub 名前を表示(name As String, job As String) ' 名前と職業を受け取る
Debug.Print "俺の名前は " & name &"、"& job "さ"
End Sub
引数の数を再確認しましょう。
引数を片方しか渡したくない場合は、(“第一引数”, “”)や(“”, “第二引数”)などど空欄を渡すことで、エラーを回避できる場合があります。
最後に
VBA(Excelマクロ)のCallについて解説いたしました。
当ブログでは、VBAマクロやPythonなど、時間を生み出すプログラミング術を公開しております。
この記事がわかりやすいと感じた方は、他の記事も読んでいってください。
最後までお読みいただき、ありがとうございました。がんばってください!