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 は型が厳密に一致しないと落ちやすい → ByVal や Variant で回避
- Split は Variant配列 → String()にそのまま渡さない(詰め替え or Variant受け)
- Range.Value は2次元配列になりやすい → 1次元扱いしない
- まず IsArray で配列かどうか判定すると事故が減る
「配列の引数で型が一致しません」は一見むずかしく見えますが、
原因をパターン分けして対処すれば、ほとんど解決できます。


コメント