プロシージャ
・引数の意味
・引数の宣言
・値渡しと参照渡し
【ここでのポイント】
Sub
Function
ByVal
ByRef
Optional
ここがあやふやではマクロ作成などできません。
Functionの戻り値と、ByVal、ByRefでの動作違い、これにOptionalが関係してくるくらいでしょう。
逆に言えば、しっかり点を稼いでおく場所になると思います。
引数の意味
適切な機能単位で作られた複数のプロシージャを連続実行することで複雑な処理を実現します。
省略可能なキーワードです。
指定するときは、引数リスト (引数 argumentlist) をかっこで囲む必要があります。
必ず指定します。
呼び出すプロシージャの名前を指定します。
省略可能です。
呼び出すプロシージャーにデータを渡すための引数です。
Callステートメントのargumentlist、これが引数と呼ばれるものです。
呼び出されたプロシージャーは、この引数を受け取って処理を実行します。
Callする時の引数が変化すれば、プロシージャーの結果が変わってきます。
Sub sample()
Dim i As Long
i = 1
Call sample2(i)
i = 2
Call sample2(i)
End Sub
Sub sample2(i)
Cells(i, 1) = i
End Sub
上記では、
sample2へiを渡す ・・・ sample
引数iを受け取る ・・・ sample2
Cells(i, 1) = i ・・・ sample2
i = 2 ・・・ sample
sample2へiを渡す ・・・ sample
引数iを受け取る ・・・ sample2
Cells(i, 1) = i ・・・ sample2
実行結果は、
A1セルに1、A2セルに2が入ります。
引数の宣言
SubプロシージャーとFunctionプロシージャーがあります・
それぞれ、
SubステートメントとFunctionステートメントをになります。
Subプロシージャーは値を返しません。
Functionプロシージャーは値を返します。
Functionプロシージャは、独自の関数を作るものだと理解してください。
[statements]
[Exit Sub]
[statements]
スコープと聞いて直ぐに理解できない場合は、ベーシックの変数と定数を見直してください。
[(arglist)]
これが引数です。
引数が無い場合や、あっても省略できる場合があります。
Functionステートメント
[statements]
[name = expression]
[Exit Function]
[statements]
[name = expression]
・・・
End Function
戻り値のデータ型を指定できます。
省略した時は、Variant型になります。
Sub sample1()
Dim vrt1
vrt1 = func1
MsgBox vrt1
End Sub
Function func1()
func1 = "func1の回答"
End Function
Functionの戻り型は省略しています。
Functionで値を戻す場合は、Functionのnameに対して値を代入します。
つまり、Functionプロシージャー名に値を入れる事で値を戻します。
上記のsample1を実行すると、"func1の回答"がメッセージ表示されます。
MsgBox func1
と1行で書く事ができます。
上記では、動作を理解しやすいように一度変数に入れています。
Sub sample2()
MsgBox func2("Functionの", "サンプルです")
End Sub
Function func2(arg1, arg2) As String
func2 = arg1 & arg2
End Function
Functionの戻り型をStringで指定しています。
上記のsample2を実行すると、"Functionのサンプルです"とメッセージ表示されます。
Sub sample3()
MsgBox func3(100, 200)
End Sub
Function func3(arg1 As Long, arg2 As Long) As Long
func3 = arg1 + arg2
End Function
Functionの戻り型をLong、引数の型もLongで指定しています。
上記のsample3を実行すると、"300"とメッセージ表示されます。
引数の構文
Optional |
省略可能です。 |
ByVal |
省略可能です。 |
ByRef |
省略可能です。 |
ParamArray |
省略可能です。 |
varname |
必ず指定します。 |
type |
省略可能です。 |
defaultvalue |
省略可能です。 |
ParamArrayは配列の引数になりますが、これについては解説を省略します。
実務ではほとんど使う事もありませんし、試験として出題されることもないはずです。
ByRefは参照渡し
これらについては、次の段落で説明します。
Sub sample()
Call sample2("引数")
Call sample2
Call sample3
End Sub
Sub sample2(Optional sMsg = "初期値")
MsgBox sMsg
End Sub
Sub sample3(Optional sMsg)
If IsMissing(sMsg) Then
sMsg = "省略"
End If
MsgBox sMsg
End Sub
sample2では、初期値を指定していますので、
Callで省略されたときは、その初期値を受け取ることになります。
IsMissing関数で、引数が省略されているかどうかを判定しています。
引数
初期値
省略
この順に、メッセージボッスに出力されます。
特定の初期値を指定しておけば、それで判定できるからです。
引数に関するエラー
ByValとByRefでエラーとなる状況が全く違ったものとなります。
ByRefでデータ型が違う場合
配列全体を引数で渡す場合
ByValでは文法エラーとなります。
Sub sample(ByRef ary()) ・・・ OK
Sub sample2(ByVal ary)
これなら、Callの引数に配列を指定できますので、
結果として配列をByValで渡していることになります。
実際には配列としてではなく、Variant(何でも入れられるので配列も入れられる)で受け取っているという事です。
ただし、さすがに試験には出ないと思います。
個々の要素は、Dimで宣言した1つの変数と同じものです。
値渡しと参照渡し
ByValが値渡し、ByRefが参照渡しです。
変数の中のデータを渡すもので、呼出側の変数は影響を受けません。
つまり、値渡しでは、呼び出し先で引数の値を変更しても、呼び出し元の引数は変更されません。
変数そのものを渡すもので、呼出側の変数が影響を受けます。
つまり、参照渡しでは、呼び出し先で引数の値を変更すると、呼び出し元の引数も変更されます。
Sub sample1()
Dim i, j
i = 1
j = 1
Call sub1(i, j)
MsgBox i
MsgBox j
End Sub
Sub sub1(arg1, arg2)
arg1 = arg1 + 1
arg2 = arg2 + 2
End Sub
上記のsample1を実行すると、2,3の順にメッセージ表示されます。
ByValもByRef指定していないので、ByRefとなっています。
この場合、参照渡しとなり、Call元のプロシージャーの引数も変更されます。
Sub sample2()
Dim i, j
i = 1
j = 1
Call sub2(i,
j)
MsgBox i
MsgBox j
End Sub
Sub sub2(ByVal arg1, ByVal
arg2)
arg1 = arg1 + 1
arg2 = arg2 + 2
End
Sub
上記のsample2を実行すると、1,1の順にメッセージ表示されます。
ByValを指定しているので、値渡しとなっています。
この場合、Call元のプロシージャーの引数は変更されません。
実際のVBAコードを見たときに、挙動を直ぐに理解できるかどうかが問題です。
サンプルコードを自分で書いて、ステップ実行しながら、変数の変化をしっかりと目で確認してください。
VBAコードを見るだけで、動作結果がわかるようになるまで繰り返し練習したほうが良いでしょう。
Sub sample1()
Dim i As Long
i = 1
sample2 (i)
MsgBox i
End Sub
Sub sample2(ByRef i As Long)
i = 2
End Sub
上記のMsgBoxの結果は、どうなるでしょうか?
1
になります。
この括弧は、括弧内の式や変数を評価し、値を取得しています。
つまり、(i)は数値定数と同じことになります。
つまり、
sample2 1
を実行していることになります。
例えByRefでも、定数は変更されません。
実務では、稀に見かけるバグになります。
引数にオブジェクトを指定した時の注意
Sub sample()
Dim MyRange As Range
Set MyRange = Range("A1")
Call sample2(MyRange)
End Sub
Sub sample2(ByVal MyRange As Range)
MyRange.Value = 1
End Sub
上記の結果は、A1セルに1が入ります。
つまり、
ByValで渡されたオブジェクトに変更を加えれば、呼出元でもオブジェクトは変更されています。
Range以外の他のオブジェクトでも同じことです。
呼び出されたプロシージャー内で、
引数の変数に対して、Setステートメントで新たなオブジェクトを入れた場合に、
その新たなオブジェクトが、呼び出し元に影響を与えるかどうかになります。
ByValなら呼び出し元は影響を受けず、ByRefなら呼び出し元は影響を受けます。
その時の、値渡し、参照渡しの違いについてまでは出題されないと思います。
【業務改善の実務】
プロシージャーを適切な機能単位で作成することが肝になります。
そして、その時の引数の使い方こそ、VBAスキルが現れてくる部分になってきます。
VBAの質としては、良くないものという事になります。
マクロを書く上では、省略して全てByRef扱いで作成することも可能ですが、
それは、動作結果の正否の問題ではなく、
そのプロシージャーが何をしているかを伝える事を怠っていることで、読みづらいVBAという事になります。
【本サイト内の関連ページ】
値渡し、参照渡しについて(ByVal,ByRef)
VBAエキスパート公式テキスト
こちらは必須として購入した方が良いでしょう。
ちょっと高いなーとは思いますが、
書籍を購入することで、学習用データが提供されています。
・サンプルブック
・VBAエキスパート模擬問題
これらが使えるようになります。
このシリーズでは、テキストを読みながら学習していることを前提とします。
同じテーマ「VBAエキスパート対策」の記事
デバッグデの基礎
マクロの実行
VBAベーシック試験対策まとめ
プロシージャ
イベント
ステートメント(スタンダード)
関数
エラーへの対処
APIとOLEオートメーション
変数と配列
レジストリの操作
新着記事NEW ・・・新着記事一覧を見る
TRIMRANGE関数(セル範囲をトリム:端の空白セルを除外)|エクセル入門(2024-08-30)
正規表現関数(REGEXTEST,REGEXREPLACE,REGEXEXTRACT)|エクセル入門(2024-07-02)
エクセルが起動しない、Excelが立ち上がらない|エクセル雑感(2024-04-11)
ブール型(Boolean)のis変数・フラグについて|VBA技術解説(2024-04-05)
テキストの内容によって図形を削除する|VBA技術解説(2024-04-02)
ExcelマクロVBA入門目次|エクセルの神髄(2024-03-20)
VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
アクセスランキング ・・・ ランキング一覧を見る
1.最終行の取得(End,Rows.Count)|VBA入門
2.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.繰り返し処理(For Next)|VBA入門
5.RangeとCellsの使い方|VBA入門
6.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
7.セルのクリア(Clear,ClearContents)|VBA入門
8.メッセージボックス(MsgBox関数)|VBA入門
9.条件分岐(Select Case)|VBA入門
10.マクロとは?VBAとは?VBAでできること|VBA入門
- ホーム
- マクロVBA入門編
- VBAエキスパート対策
- プロシージャ
このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。