【初心者向け】Excel VBAの「プロシージャ」とは?基本の種類と使い方を徹底解説
プロシージャとはひとまとまりの処理単位です。
SubプロシージャはExcelのマクロから呼び出せる?それを書く
1. プロシージャとは?(プログラムの実行単位)
VBAにおけるプロシージャとは、一言で言えば**「ひとまとまりの処理の単位」**のことです。
Excelに「セルの色を変えて」「文字を入力して」「保存する」といった指示を出すとき、これらを一つの箱に入れて名前を付けたものがプロシージャになります。
2. プロシージャの主な種類
VBAには主に3つのプロシージャがありますが、基本として以下の2つを覚えておけばOKです。
① Sub(サブ)プロシージャ
最も一般的なプロシージャです。実行すると、記述された処理を上から順番に行います。「マクロを実行する」と言ったときは、このSubプロシージャを指すことがほとんどです。
- 特徴: 返り値(実行結果のデータ)を持たない。
- 用途: セルの操作、シートの作成、データの転記など。
② Function(ファンクション)プロシージャ
特定の計算を行い、その結果を返すプロシージャです。「ユーザー定義関数」として、Excelのセル上で =MYTAX(A1) のように自作関数として使うこともできます。
- 特徴: 処理の結果(戻り値)を呼び出し元に返す。
- 用途: 複雑な計算、特定の条件判定など。
このほかにPropertyプロシージャというものが
3. プロシージャの基本構成(書き方)
実際のコードの書き方を見てみましょう。
Subプロシージャの例
Subプロシージャの構文は次の通りです。
Sub 名前(引数リスト)
プロシージャ本体
End Sub
Subプロシージャを定義は、Subキーワードの行で始まります。Subの後にはプロシージャの名前と()が続きます。()内には0個以上の引数のリストを記載することが出来ます。Subキーワード行(プロシージャ宣言と呼ばれる)の次の行からはプロシージャ本体として命令文(ステートメント)を記述します。そしてプロシージャ定義はEnd Sub行で終わります。
Sub GreetUser()
' メッセージを表示するだけのシンプルな処理
MsgBox "こんにちは!VBAの世界へようこそ。"
End Sub
Functionプロシージャの例
Functionプロシージャの構文は次の通りです。
Function 名前(引数リスト) As データ型
プロシージャ本体
名前 = 戻り値
End Function
Functionプロシージャを定義は、Functionキーワードの行で始まります。Functionの後にはプロシージャの名前と()が続きます。()内には0個以上の引数のリストを記載することが出来ます。()の後ろにはAsに続けて戻り値のデータ型を指定できます。これを省略した場合、戻り値のデータ型はVariant型として扱われます。
Subキーワード行(プロシージャ宣言と呼ばれる)の次の行からはプロシージャ本体として命令文(ステートメント)を記述します。そしてプロシージャ定義はEnd Function行で終わります。
VBA
Function AddNumbers(a As Double, b As Double) As Double
' 2つの数値を足した結果を返す
AddNumbers = a + b
End Function
1. 引数リストの構文
引数はプロシージャ宣言の1行目に、以下のような形式で記述します。
プロシージャの()内には引数のリストを記述できます(省略可能)。構文は次の通りです。複数の引数が必要な場合は、カンマ , で区切って並べます。
引数名 As データ型 ' 引数が1つの場合
引数名1 As データ型, 引数名2 As データ型, ... ' 引数が2つ以上の場合
データ型の指定(As データ型部分)は省略可能です。その場合、引数のデータ型はVariant型として扱われます。
プロシージャの呼び出し方
Subプロシージャの呼び出し方は次の2通りの方法があります。
| 呼び出し方 | 説明 |
|---|---|
| Subプロシージャ名 引数1, 引数2 | 引数をかっこで囲まない。 |
| Call Subプロシージャ名(引数1, 引数2) | Callステートメントを使う。この場合はかっこで囲む。 |
Subプロシージャの呼び出し方
Functionプロシージャは次の3通りです。
| 呼び出し方 | 説明 |
|---|---|
| Functionプロシージャ名 引数1, 引数2 | 戻り値を使用しない場合、引数をかっこで囲まない。 |
| Call Functionプロシージャ名(引数1, 引数2) | 戻り値を使用しない場合はCallステートメント使って 呼び出すこともできる。引数はかっこで囲む。 |
| Functionプロシージャ名(引数1, 引数2) | 戻り値を使用する場合、引数をかっこで囲む。 |
Functionプロシージャの呼び出し方
この後は、それぞれの呼び出し方を注意点や実例を交えながら説明します。
Subプロシージャを呼び出す
Subプロシージャを他のプロシージャから呼び出すには、プロシージャ名と必要な引数を記述します。Callステートメントは必須ではありませんが、使用する場合は引数をかっこで囲む必要があります。
プロシージャ名 引数リスト
Call プロシージャ名(引数リスト)
引数が複数ある場合はカンマ(,)で区切って指定します。
Sub main()
addAndMsg 3, 5
End Sub
Sub addAndMsg(foo, bar)
MsgBox foo + bar
End Sub
Functionプロシージャを呼び出す
Functionプロシージャ(関数)で戻り値を使用する場合、引数をかっこで囲んで呼び出す必要があります。
変数 = プロシージャ名(引数リスト)
Set 変数 = プロシージャ名(引数リスト)
Functionプロシージャがオブジェクトを返す場合は、オブジェクト変数に代入するためにSetステートメントが必要です。
戻り値を使用しない場合は、Subプロシージャと同じ方法で呼び出すことも出来ます。
次の例は戻り値を直接MsgBox関数の引数に渡しています。
Sub main()
MsgBox add(3, 5)
End Sub
Function add(foo, bar)
add = foo + bar
End Function
引数の渡し方
引数はかっこで囲んだり、囲まなかったりしますが引数のリストの指定の方法に違いはありません。代表的な渡し方を紹介します。ほとんどの場合はこれだけ知っていれば大丈夫です。
位置引数で渡す
引数のリストはカンマ(,)で区切って指定しますが、引数を渡す順序はプロシージャの定義の順序通りに渡す必要があります。引数の位置が決まっているので位置引数と呼ばれます。
例えば、MsgBox関数には1つ目の引数にメッセージ文字列、3つ目の引数としてダイアログボックスのタイトルを指定します。2つ目の引数は省略可能してますが、省略する場合でもカンマは2つ必要です。
Sub sample()
MsgBox "マクロ実行中です。", , "インフォメーション"
End Sub
名前付き引数
引数が多数あるプロシージャで必要な引数だけ渡したい場合、名前付き引数を使うと便利です。名前付き引数を使うと必要な引数だけ、そしてプロシージャの定義とは異なる順序で引数を渡すことができます。
名前付き引数は、引数名の後ろに「:=」を記述し、その後に値を指定します。
引数名1:=値1, 引数名2:=値2, ...
前述のMsgBoxを呼び出す例を、名前引数を使って呼び出すと次のようになります。
Sub sample()
MsgBox Prompt:="マクロ実行中です。", Title:="インフォメーション"
End Sub
4. 知っておきたい「スコープ(適用範囲)」
プロシージャの宣言の前に Public や Private をつけることで、そのプロシージャがどこから呼び出せるかを決められます。
| キーワード | 意味 | 詳細 |
| Public | 公開 | 他のモジュールからも呼び出せる(省略時のデフォルト)。 |
| Private | 非公開 | 同じモジュール内からしか呼び出せない。 |
Google スプレッドシートにエクスポート
Tips: > マクロの一覧画面(Alt + F8)に表示させたくない補助的なプロシージャには
Privateをつけるのが一般的です。
高度な機能あれこれ(これは別記事?)
プロシージャ宣言のカッコ ( ) の中に記述する引数には、いくつかの種類と決まった構文(書き方)があります。これらを使い分けることで、より柔軟なプログラムを組むことが可能になります。
1. 引数リストの構文
引数はプロシージャ宣言の1行目に、以下のような形式で記述します。
プロシージャの()内には引数のリストを記述できます(省略可能)。構文は次の通りです。複数の引数が必要な場合は、カンマ , で区切って並べます。
引数名 As データ型 ' 引数が1つの場合
引数名1 As データ型, 引数名2 As データ型, ... ' 引数が2つ以上の場合
データ型の指定(As データ型部分)は省略可能です。その場合、引数のデータ型はVariant型として扱われます。
2. 「参照渡し」と「値渡し」
引数の渡し方には、参照渡しと値渡しという2つの方法があります。
① ByVal(値渡し)
元の変数の「コピー」を渡します。プロシージャ内で引数の値を書き換えても、呼び出し元の元の変数には影響しません。引数を値渡しで渡す場合、次のように引数名の前にByValキーワードを指定します。
ByVal 引数名 As データ型
② ByRef(参照渡し)
元の変数の「保存場所(アドレス)」を直接渡します。プロシージャ内で引数を書き換えると、呼び出し元の元の変数の値も変わります。引数を参照渡しで渡す場合、次のように引数名の前にByRefキーワードを指定します。ByValもByRefも指定しない場合は参照渡しになります。
ByRef 引数名 As データ型
③ Optional(省略可能引数)
呼び出し側で、その引数を「渡しても渡さなくても良い」状態にします。
- ルール: Optionalを付けた引数より後ろの引数は、すべてOptionalにする必要があります。
- 構文:
(Optional price As Long = 100)※= 100のように初期値を設定できます。
④ ParamArray(可変個引数)
引数の個数が決まっていない場合に使用します。渡されたデータは「配列」として扱われます。
- ルール: 引数リストの最後に1回だけ使用可能です。必ず
Variant型の配列になります。 - 構文:
(ParamArray values())
3. 引数の種類まとめ一覧表
4. 実践的な使い分けのポイント
実務では、基本的には ByVal(値渡し) を使うことを強く推奨します。
なぜなら、ByRef(デフォルト)だと、プログラムのどこで変数の値が変わったのかを追跡するのが難しくなり、バグの原因になりやすいからです。明示的に「元の値を変えたい」という目的があるときだけ ByRef を使うようにしましょう。
まとめ
引数の種類を理解することで、一つのプロシージャを「汎用的な部品」として活用できるようになります。
- ByVal で値を保護し、
- Optional で使い勝手を良くし、
- ParamArray で柔軟に対応する。
この3つを意識して、メンテナンスしやすいVBAコードを目指しましょう!
次のステップ
次は、実際に引数を使ったプロシージャ同士で、**「どのようにデータをやり取りするのか(呼び出し側と受け取り側の関係)」**について、具体的なデバッグ方法を交えて解説しましょうか?
Subの場合
Sub SampleProcedure(ByVal value As Long)
MsgBox value
End Sub
呼び出し側:
Call SampleProcedure(10)
または
SampleProcedure 10
Functionの場合
Function AddNumbers(ByVal a As Long, ByVal b As Long) As Long
AddNumbers = a + b
End Function
呼び出し:
Dim result As Long
result = AddNumbers(5, 3)
2. 引数の構文の基本形
Sub プロシージャ名( _
ByVal 変数名 As データ型, _
ByRef 変数名 As データ型 _
)
構成要素
| 要素 | 意味 |
|---|---|
| ByVal | 値渡し(コピーを渡す) |
| ByRef | 参照渡し(元の変数を渡す) |
| 変数名 | 任意 |
| As 型 | データ型指定 |
※ByRefは省略可能(省略するとByRef)
3. ByVal と ByRef の違い(重要)
ByVal(値渡し)
Sub Test(ByVal x As Long)
x = x + 1
End Sub
呼び出し:
Dim a As Long
a = 5
Test a
MsgBox a '→ 5 のまま
特徴
- 値のコピーが渡る
- 元の変数は変更されない
- 安全性が高い
ByRef(参照渡し)
Sub Test(ByRef x As Long)
x = x + 1
End Sub
呼び出し:
Dim a As Long
a = 5
Test a
MsgBox a '→ 6 に変わる
特徴
- 元の変数が直接渡される
- 呼び出し元も変更される
- 高速だが副作用あり
4. 省略可能な引数(Optional)
Sub Sample(Optional ByVal message As String = "Hello")
MsgBox message
End Sub
呼び出し:
Sample 'Hello
Sample "Test" 'Test
ポイント
- Optionalは必ず最後に書く
- デフォルト値を設定可能(基本型のみ)
5. 可変長引数(ParamArray)
Sub Sample(ParamArray values() As Variant) Dim i As Long
For i = LBound(values) To UBound(values)
Debug.Print values(i)
Next iEnd Sub
呼び出し:
Sample 1, 2, 3, "ABC"
特徴
- 引数の数が不定
- 配列として受け取る
- 型はVariant固定
6. オブジェクトを引数として渡す
Sub SetColor(ByVal ws As Worksheet)
ws.Range("A1").Interior.Color = vbYellow
End Sub
呼び出し:
SetColor Worksheets("Sheet1")
ポイント
- オブジェクトは常に参照型
- Setは呼び出し側で必要
7. 配列を渡す
Sub ShowArray(ByRef arr As Variant) Dim i As Long
For i = LBound(arr) To UBound(arr)
Debug.Print arr(i)
Next iEnd Sub
呼び出し:
Dim v As Variant
v = Array(1, 2, 3)ShowArray v
8. 引数の型を省略した場合
Sub Sample(x)
→ Variant型になります。
実務では非推奨
- 型安全性が低い
- バグの原因になる
9. 呼び出し時の注意(Callと括弧)
Callを使う場合
Call SampleProcedure(10)
Callを使わない場合
SampleProcedure 10
※括弧を付けるとエラーになるケースあり
10. 実務でのベストプラクティス
✔ 可能な限り ByVal を使う
✔ 型は必ず明示する
✔ オブジェクトは明示的に渡す
✔ Optionalは乱用しない
✔ ParamArrayはAPI的設計時のみ
まとめ
VBAの引数構文は以下が基本です。
Sub Sample(ByVal a As Long, Optional ByVal b As String = "")
重要なのは:
- ByVal(安全)
- ByRef(元が変わる)
- Optional(省略可能)
- ParamArray(可変長)
さらに深掘りできます:
- ByValでもオブジェクトが変更できる理由
- 引数の型不一致エラーの本質
- FunctionとSubの設計思想の違い
- VBAにおける参照型と値型の内部構造
どのテーマを掘り下げますか?