VBA入門
引数の数を可変にできるパラメーター配列(ParamArray)

ExcelマクロVBAの基本と応用、エクセルVBAの初級・初心者向け解説
公開日:2019-10-07 最終更新日:2021-12-16

第133回.引数の数を可変にできるパラメーター配列(ParamArray)


Subプロシージャー、Functionプロシージャーにおいて、
引数リストの数を特定せず、不定個数の引数を渡せるよう可変にしたい場合があります。


ワークシートの関数では、引数の個数が不定の関数が多数あります。
=SUM(数値1,数値2,...)
このように、最後が「,...」となっていて、いくつでも(限度はありますが)指定できる関数です。

マクロVBAのプロシージャーで、これと同様に引数を可変で定義するためには、
ParamArrayキーワード(パラメーター配列)を使用します。
以下では、引数の構文と名前付き引数について確認しつつParamArrayについて解説します。


引数の構文

Sub name [(arglist)]
Function name [(arglist)] [As type]

arglistは次の形式で指定します。

[Optional] [ByVal | ByRef] [ParamArray] varname[( )] [As type] [= defaultvalue]

Optional

省略可能です。
指定した引数が省略可能であることを示します。
このキーワードを指定した場合、引数 arglist のそれ以降の引数も省略可能でなければならず、すべてキーワード Optional を付けて宣言する必要があります。
キーワード ParamArray を使った場合は、どの引数に対してもキーワード Optional は指定できません。

ByVal

省略可能です。
その引数が、値渡しで渡されることを示します。

ByRef

省略可能です。
その引数が、参照渡しで渡されることを示します。
既定値は ByRef です。

ParamArray

省略可能です。
引数 arglist の最後の引数でのみ使用できます。
その引数がバリアント型 (Variant) の要素を持つ省略可能 (Optional) な 配列であることを示します。
キーワード ParamArray を使うと、任意の数の引数を渡すことができます。
ByVal、ByRef、Optional の各キーワードと共に使うことはできません。

varname

必ず指定します。
引数を表す変数名を指定します。
変数の標準的な名前付け規則に従って指定します。

type

省略可能です。
プロシージャに渡す引数のデータ型を指定します。
バイト型 (Byte)、ブール型 (Boolean)、整数型 (Integer)、長整数型 (Long)、通貨型 (Currency)、単精度浮動小数点数型 (Single)、倍精度浮動小数点数型 (Double)、10 進型 (Decimal) (現在はサポートされていません)、日付型 (Date)、文字列型 (String) (可変長のみ)、オブジェクト型 (Object)、バリアント型 (Variant) のいずれかを指定できます。
パラメータにキーワード Optional が指定されていない場合は、ユーザー定義型またはオブジェクトの種類を指定することもできます。

defaultvalue

省略可能です。
任意の定数または定数式を指定します。
キーワード Optional を指定したパラメータに対してのみ有効です。
データ型がオブジェクト型 (Object) の場合、明示的な既定値は Nothing だけです。


ByValの値渡しとは
変数の中のデータを渡すもので、呼出側の変数は影響を受けません。
つまり、値渡しでは、呼び出し先で引数の値を変更しても、呼び出し元の引数は変更されません。

ByRefの参照渡しとは
変数そのものを渡すもので、呼出側の変数が影響を受けます。
つまり、参照渡しでは、呼び出し先で引数の値を変更すると、呼び出し元の引数も変更されます。


名前付き引数について

通常、複数の引数がある場合は、その順番通りに指定します。
先頭より、
第1引数, 第2引数, 第3引数, ・・・ 
と呼びます。

しかし、
引数の数が多いと、何番目なのかを意識することは面倒になりますし混乱します。
そこで、
引数に名前を付けて、その名前で指定できるようにしてあります。
それが、
名前付き引数です。

名前付き引数を指定する場合は、
名前付き引数名:=値
このように、:=で値を指定します。


ParamArrayキーワード(パラメーター配列)とは

引数リストでキーワードParamArrayを使うと、任意の数の引数を渡すことができます。
ParamArrayキーワードは、その引数がバリアント型(Variant)の要素を持つ省略可能(Optional)な配列であることを示します。

ParamArrayキーワードの制限

引数リストの最後の引数でしか使用できない
ParamArrayキーワードを指定した引数より後ろには、他の引数を指定できません。

ByVal、ByRef、Optionalの各キーワードと共に使うことはできない
ParamArrayキーワードを指定した引数は、ByRefかつOptionalになります。
ByVal,ByRefやOptionalの指定はできません。

データ型はVaiantのみ
ParamArrayキーワードを指定した引数はVariant固定となります。
Variant以外の型を指定した場合はエラーとなります。

名前付き引数は使えません
呼び出し時に、名前付き引数と共に使う事はできません。
ParamArray引数を指定する場合には、名前付き引数を使うことはできません。
ただし、ParamArray引数を省略する場合には名前付き引数を使う事はできます。


呼び出し時に、ParamArray引数を省略した場合

IsMissing関数の戻り値がTrueとなります。
UBound関数の戻り値が-1となります。

ParamArray引数が省略されたかどうかは、上記のどちらかを使用して判断します。


ParamArrayキーワード(パラメーター配列)の使用例

以下では、ParamArrayの記述だけに特化する為、データ型は全て省略しています。

ParamArrayだけの場合

Sub sample1()
  Call sample1_sub(123, "abc", #10/7/2019#)
End Sub

Sub sample1_sub(ParamArray p())
  Dim i
  For i = LBound(p) To UBound(p)
    Debug.Print p(i)
  Next
  
  Dim v
  For Each v In p
    Debug.Print v
  Next
End Sub

For~とFor Each~の2通りのサンプルになります。
ParamArray引数が省略された場合は、どちらの場合もイミディエイトには何も出力されません。


他の引数がある場合

Sub sample2()
  Call sample2_sub(123, 456, "abc")
End Sub

Sub sample2_sub(arg1, ParamArray p())
  Dim i
  For i = LBound(p) To UBound(p)
    Debug.Print p(i)
  Next
End Sub

ParamArray引数が省略された場合、
Call sample2_sub(123)
この場合はイミディエイトには何も出力されません。


ParamArray引数を省略した場合

Sub sample3()
  Call sample3_sub
End Sub

Sub sample3_sub(ParamArray p())
  If IsMissing(p) Then
    Debug.Print "引数なし"
  Else
    Debug.Print "引数あり"
  End If
  
  If UBound(p) < LBound(p) Then
    Debug.Print "引数なし"
  Else
    Debug.Print "引数あり"
  End If
End Sub

IsMissing関数で判定するほうが良いでしょう。
UBound関数で判定する場合は、-1判定でも構いませんが、
UBound < LBoundで判定するこ方法も良いと思います。


ParamArray引数を配列で返す関数

Sub sample4()
  Dim v
  v = sample4_fnc(123, "abc", #10/7/2019#)
  Debug.Print Join(v, ",")
End Sub

Function sample4_fnc(ParamArray p()) As Variant()
  Dim i, ary
  ReDim ary(LBound(p) To UBound(p))
  For i = LBound(p) To UBound(p)
    ary(i) = p(i)
  Next
  sample4_fnc = ary
End Function

ここでは配列にして返していますが、
実際は、Functionの中で配列を使って処理する場合のサンプルです。


エラーとなる記述

VBA ParamArray 引数可変

↑名前付き引数と共用出来ません。

VBA ParamArray 引数可変

↑引数の最後にのみ指定できます。

VBA ParamArray 引数可変

↑OptionalとParamArrayは同時に使う事はできません。

VBA ParamArray 引数可変

↑配列指定は必須です。

VBA ParamArray 引数可変

↑Variant以外のデータ型は指定できません。

VBA ParamArray 引数可変

↑ByVal,ByRef指定はできません。


サイト内の関連ページ

第25回.名前付き引数について
・仮引数と実引数 ・メソッドとは ・名前付き引数について ・名前付き引数の例文 ・名前付き引数の必要性
第107回.プロシージャーの引数
・引数の構文 ・引数の使用例 ・引数について

値渡し、参照渡しについて(ByVal,ByRef)
・ByVal(値渡し)とByRef(参照渡し) ・普通の変数(プリミティブ型)の場合 ・オブジェクト変数の場合 ・サイト内のByVal,ByRefの記事
IsMissing関数|ExcelマクロVBA関数
・IsMissing関数 ・IsMissing関数の使用例 ・Is○○関数一覧
VBAクラスの作り方:独自Rangeっぽいものを作ってみた
・クラスの全VBAコード ・サンプルとして使うブックの構成 ・標準モジュールでの使い方 ・最後に




同じテーマ「マクロVBA入門」の記事

第130回.テーブル操作の概要(ListObject)
第131回.テーブル操作のVBAコード(ListObject,DataBodyRange)
第142回.テーブル全件処理とデータ最終行(ListObject,DataBodyRange)
第127回.他のブックのマクロを実行(Runメソッド)
第128回.マクロをショートカットで起動(OnKeyメソッド)
第129回.レジストリの操作(SaveSetting,GetSetting,GetAllSettings,DeleteSetting)
第133回.引数の数を可変にできるパラメーター配列(ParamArray)
第134回.Errオブジェクトとユーザー定義エラー
第138回.外部ライブラリ(ActiveXオブジェクト)
第140回.Property {Get|Let|Set} ステートメント
第143回.WorksheetFunctionの効率的な使い方とスピル新関数の利用


新着記事NEW ・・・新着記事一覧を見る

VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
累計を求める数式あれこれ|エクセル関数応用(2024-01-22)
複数の文字列を検索して置換するSUBSTITUTE|エクセル入門(2024-01-03)
いくつかの数式の計算中にリソース不足になりました。|エクセル雑感(2023-12-28)
VBAでクリップボードへ文字列を送信・取得する3つの方法|VBA技術解説(2023-12-07)
難しい数式とは何か?|エクセル雑感(2023-12-07)
スピらない スピル数式 スピらせる|エクセル雑感(2023-12-06)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
4.繰り返し処理(For Next)|VBA入門
5.変数宣言のDimとデータ型|VBA入門
6.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
7.並べ替え(Sort)|VBA入門
8.条件分岐(IF)|VBA入門
9.セルのクリア(Clear,ClearContents)|VBA入門
10.マクロとは?VBAとは?VBAでできること|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ