〖ExcelVBA・マクロ〗「配列の引数で型が一致しません」の原因と対処法まとめ|ByRef/Variant/1次元2次元の落とし穴

ExcelVBA

VBAで配列を使っていると、よく出るのがこのエラーです。

  • 「型が一致しません」
  • 「ByRef 引数の型が一致しません」
  • (配列を渡したときに)「型が一致しません」

特に多いのは「配列を引数として渡した瞬間」に発生するパターンです。
この記事では、原因をパターン別に整理して、対処法をコピペOKでまとめます。


スポンサーリンク
スポンサーリンク

まず確認:配列まわりのエラーは大きく2種類

配列を引数で渡すときの「型が一致しません」は、次の2系統に分かれます。

A. コンパイルエラー(実行前に止まる)

ByRef 引数の型が一致しません

→ 引数の型が「一致」していないことが原因

B. 実行時エラー(実行中に止まる)

型が一致しません(エラー13)

→ 中身(Variantの中身)が配列じゃない/想定と違う等


イラストで理解:VBAの配列は「型」と「次元」が重要

1次元(例:String()) A B C D 2次元(例:Range.Value) 1,1 1,2 1,3 2,1 2,2 2,3 ※「型(String/Variantなど)」と「次元(1次元/2次元)」が合わないとエラーになりやすい


原因1:ByRef(参照渡し)の型が一致していない

VBAの引数は、何も書かないとByRef(参照渡し)になります。
ByRefは「受け取る側が期待する型」と「渡す側の型」がピッタリ合わないとエラーになりやすいです。

よくあるNG例:Splitの戻り(Variant配列)を String() に渡す

Sub Test()
    Dim arr As Variant
    arr = Split("A,B,C", ",")  ' Split は Variant配列

    Call UseStringArray(arr)    ' ← ここで型が一致しません系
End Sub

Sub UseStringArray(ByRef s() As String)
End Sub

対処法A:受け取る側を Variant にする(初心者に一番おすすめ)

Sub UseArraySafe(ByVal v As Variant)
    ' v は配列でも単体でも受けられる(扱う前に判定する)
End Sub

対処法B:引数を ByVal にする(型違いを回避しやすい)

Sub UseStringArray(ByVal s As Variant)
    ' Splitの結果や、Range.Valueも受け取りやすい
End Sub

※ByValにすると「参照渡しの厳密チェック」が緩くなるため、引数エラー回避に効くことが多いです。


原因2:Range.Value は「2次元配列」になりやすい

Excelの範囲をまとめて取ると、戻り値は2次元のVariant配列になるのが基本です。
これを1次元配列として扱うと、引数でもループでも崩れます。

NG例:2次元配列を1次元として渡す

Sub Test()
    Dim v As Variant
    v = Range("A1:A10").Value  ' 2次元(1 to 10, 1 to 1)

    Call Use1D(v)              ' ← 受け取り側が1次元想定だと崩れる
End Sub

Sub Use1D(ByRef arr() As Variant)
End Sub

対処法:受け取り側を Variant にして次元を確認する

Sub UseRangeValue(ByVal v As Variant)
    If IsArray(v) = False Then Exit Sub

    ' 2次元の想定で回す(行,列)
    Dim r As Long, c As Long
    For r = LBound(v, 1) To UBound(v, 1)
        For c = LBound(v, 2) To UBound(v, 2)
            ' v(r, c)
        Next c
    Next r
End Sub

原因3:Variantの中身が「配列じゃない」状態で渡している

Variant変数は便利ですが、状況によって「配列ではない値」になることがあります。
その状態で配列前提の処理(LBound/UBoundなど)をすると型不一致や別のエラーになります。

対処法:まず IsArray で判定する

Sub SafeArray(ByVal v As Variant)

    If IsArray(v) = False Then
        MsgBox "配列ではありません。", vbExclamation
        Exit Sub
    End If

    MsgBox "配列です。"

End Sub

原因4:固定長配列/動的配列/型付き配列の違いで崩れる

例えば「Long配列」には、Variant配列をそのまま渡せません。
型付き配列(Long(), String()など)は、受け取り側も渡す側も型を合わせる必要があります。

対処法:型付き配列にしたいなら「変換して詰め替える」

例:Variant配列 → String配列へ詰め替え

Function ToStringArray(ByVal v As Variant) As String()

    Dim s() As String
    Dim i As Long

    ReDim s(LBound(v) To UBound(v))

    For i = LBound(v) To UBound(v)
        s(i) = CStr(v(i))
    Next i

    ToStringArray = s
End Function

※この例は1次元配列の場合です。Range.Value(2次元)の場合は別途2次元で詰め替えが必要です。


原因5:「()」の付け方が間違っている(配列を要素として渡してしまう)

配列は「変数名だけ」で渡すのが基本です。
うっかり arr(0) と書くと「配列の0番目(要素)」を渡してしまい、型が合わずに落ちます。

Dim arr As Variant
arr = Split("A,B,C", ",")

Call UseArray(arr)     ' OK:配列を渡す
Call UseArray(arr(0))  ' NG:要素(文字列)を渡す

困ったらコレ:引数を安全に受ける「万能テンプレ」

「配列が来るかもしれないし、来ないかもしれない」
「1次元/2次元が混ざる」
こういう実務あるあるは、引数を Variant で受けて判定するのが一番安全です。

Option Explicit

Public Sub AcceptArray(ByVal v As Variant)

    If IsArray(v) = False Then
        MsgBox "配列ではありません。", vbExclamation
        Exit Sub
    End If

    ' 次元判定(雑にTryする簡易版)
    On Error GoTo OneDim

    Dim lb2 As Long
    lb2 = LBound(v, 2) ' 2次元なら取れる
    On Error GoTo 0

    ' 2次元
    Dim r As Long, c As Long
    For r = LBound(v, 1) To UBound(v, 1)
        For c = LBound(v, 2) To UBound(v, 2)
            ' Debug.Print v(r, c)
        Next c
    Next r
    Exit Sub

OneDim:
    On Error GoTo 0

    ' 1次元
    Dim i As Long
    For i = LBound(v) To UBound(v)
        ' Debug.Print v(i)
    Next i

End Sub

まとめ:配列引数の型不一致は「ByRef」「Variant」「次元」が原因

  • ByRef は型が厳密に一致しないと落ちやすい → ByValVariant で回避
  • Split は Variant配列 → String()にそのまま渡さない(詰め替え or Variant受け)
  • Range.Value は2次元配列になりやすい → 1次元扱いしない
  • まず IsArray で配列かどうか判定すると事故が減る

「配列の引数で型が一致しません」は一見むずかしく見えますが、
原因をパターン分けして対処すれば、ほとんど解決できます。

スポンサーリンク
スポンサーリンク
ExcelVBA
いがぴをフォローする

コメント

タイトルとURLをコピーしました