ExcelVBAでプロシージャや関数を作っていると、「受け取った引数が配列かどうか分からずエラーになった」「オブジェクト変数なのに通常の変数として扱ってしまいエラーが出た」「Optional引数が省略されたかどうかを判定できない」といった悩みに直面することがあります。
こうした悩みを解決してくれるのが、IsArray関数・IsObject関数・IsMissing関数です。いずれも「変数や引数の状態を安全に判定する」ための関数で、汎用的なプロシージャを作るときに欠かせません。
この記事では、3つの関数の基本的な使い方から、実務でよくある「引数チェック処理」への組み込み方まで解説します。
IsArray関数の使い方
IsArray関数は、指定した変数が配列かどうかを判定します。配列を受け取る想定のプロシージャで、誤って単一の値が渡された場合にエラーを防ぐのに役立ちます。
Sub Sample_IsArray()
Dim numbers(1 To 3) As Long
Dim singleValue As Long
numbers(1) = 10
numbers(2) = 20
numbers(3) = 30
singleValue = 100
Debug.Print IsArray(numbers) ' True
Debug.Print IsArray(singleValue) ' False
End Sub
実務では、次のように「配列を受け取る前提のプロシージャ」の先頭でチェックすると安全です。
Sub PrintArrayItems(ByVal target As Variant)
Dim i As Long
If Not IsArray(target) Then
MsgBox "配列を渡してください。"
Exit Sub
End If
For i = LBound(target) To UBound(target)
Debug.Print target(i)
Next i
End Sub
引数の型をVariantにしておくことで、配列以外の値が渡されてもエラーで停止せず、メッセージを出して安全に処理を終了できます。
IsObject関数の使い方
IsObject関数は、指定した変数がオブジェクト型(またはオブジェクトを格納できるVariant型)かどうかを判定します。数値や文字列などの値型と、Rangeやワークシートなどのオブジェクト型を区別したいときに使います。
Sub Sample_IsObject()
Dim rng As Range
Dim num As Long
Set rng = ThisWorkbook.Worksheets(1).Range("A1")
num = 10
Debug.Print IsObject(rng) ' True
Debug.Print IsObject(num) ' False
End Sub
注意点として、IsObjectはあくまで「オブジェクト型かどうか」を判定するものであり、「実体を持っているかどうか」までは判定しません。オブジェクト変数にSetしていても、参照先が存在しない状態(Nothing)であればIsObjectの結果はTrueのままです。実体の有無を確認したい場合は、次のようにIs Nothingと組み合わせます。
Sub Sample_IsObjectWithNothing()
Dim rng As Range
If IsObject(rng) Then
If rng Is Nothing Then
Debug.Print "オブジェクト型だが、まだ何も参照していません"
End If
End If
End Sub
IsMissing関数の使い方
IsMissing関数は、Optionalで宣言した引数が呼び出し時に省略されたかどうかを判定します。デフォルト値を設定できない場面(オブジェクト型の引数など)で特に活躍します。
IsMissingを使うには、対象の引数をVariant型でOptional宣言しておく必要がある点に注意してください。数値型や文字列型でOptional宣言した引数には使えません。
Sub Sample_IsMissing()
Call ShowGreeting("鈴木")
Call ShowGreeting("佐藤", "さん")
End Sub
Sub ShowGreeting(ByVal userName As String, Optional ByVal honorific As Variant)
Dim h As String
If IsMissing(honorific) Then
h = "様"
Else
h = honorific
End If
MsgBox userName & h
End Sub
このように、honorificが省略されたかどうかをIsMissingで判定し、省略時のデフォルト値を自前で設定しています。数値や文字列であればOptional ByVal honorific As String = "様"のようにデフォルト値を直接指定できますが、オブジェクト型の引数はデフォルト値を指定できないため、IsMissingによる判定が必須になります。
3つの関数を組み合わせた引数チェックの実践例
汎用的なプロシージャを作る際は、受け取った引数の状態を先頭でまとめてチェックしておくと、後続の処理でエラーが起きにくくなります。
Sub ProcessData(ByVal target As Variant, Optional ByVal option1 As Variant)
' 引数が配列かどうかをチェック
If Not IsArray(target) Then
MsgBox "targetには配列を渡してください。"
Exit Sub
End If
' Optional引数が省略されたかどうかをチェック
If IsMissing(option1) Then
Debug.Print "option1は省略されました。デフォルト処理を実行します。"
ElseIf IsObject(option1) Then
Debug.Print "option1にオブジェクトが渡されました。"
Else
Debug.Print "option1に値が渡されました:" & option1
End If
' 以降、配列targetに対する処理を記述
End Sub
このように先頭でガード処理を入れておくことで、想定外の引数が渡されたときにいきなり実行時エラーで止まるのではなく、分かりやすいメッセージを出して安全に処理を終了できます。
まとめ
IsArray関数は、変数が配列かどうかを判定する。配列を受け取るプロシージャの先頭でのチェックに便利IsObject関数は、変数がオブジェクト型かどうかを判定する。実体の有無までは判定しないため、Is Nothingとの併用が必要な場合があるIsMissing関数は、OptionalかつVariant型で宣言した引数が省略されたかどうかを判定する。オブジェクト型引数のデフォルト値代わりとして使える
いずれも単体で使うというより、「想定外の値が渡されたときにエラーで止まらず安全に処理する」ためのガード処理として組み合わせて使うのがポイントです。汎用的なプロシージャや共通関数を作る際は、ぜひ活用してみてください。


コメント