型が一致しません。

エラー表示

このエラーが発生すると、マクロ起動時(コンパイル時)に次のエラーが表示されます。
実行時エラー '13'

型が一致しません。

エラーの発生理由について

Microsoft公式の解答

Microsoft公式によると次のようにあります。

Visual Basic では、多くの値を変換したり強制的に指定したりすることにより、以前のバージョンでは不可能だったデータ型の代入が実現されています。
それでも、このエラーが発生する場合があります。このエラーの原因と解決策を以下に示します。
(以下略)

公式HPで解決策も記載してくれているのですが、正直パッとしない印象です。大半の読者は「そんなこと分かってるよ!」と思うことでしょう。そのため、本ページで詳しく見てみましょう。

【原因1】数値型や日付型の変数に文字を代入

文字列以外の数値型や日付型等の変数(プリミティブ型)に文字を代入すると、本エラーが発生します。

例1:数値型や日付型の変数に文字を代入

'数値型や日付型の変数に文字を代入した
Sub ErrSample1()
    ' Dim str As "String" と書いたつもり
    Dim str As Long
    ' ↓ここで数値型の変数に文字を代入したためエラー
    str = "test"
    MsgBox str
End Sub

【原因2】数値と文字で加算等の計算

Variant型を使用すると、マクロを作成する時は楽になる場合がありますが、キチンと管理しないと、予期せぬエラーが起こりやすくなります。 次の例では、数値を入れる変数に誤って文字を代入してしまったパターンです。

例1:数値と文字で加算の計算した①

Sub ErrSample2_1()
    Dim num1 As Variant
    Dim num2 As Variant
    num1 = "aaa"        ' 本当は数値を代入するハズだった
    num2 = 10
    MsgBox num1 + num2  ' ←ここでエラーになる
End Sub

変数をVariant型で作成している場合、数値を代入する予定なのに誤って文字列を入れた場合、問題なくコンパイルが通ってしまいます。 そして、そのマクロを使用した時に「実行時エラー」となってユーザーを襲撃してきます。 コピペを多用するとこのミスが起こりやすいです。

例2:数値と文字で加算の計算した②

Sub ErrSample2_2()
    Dim num1 As Variant
    Dim num2 As Variant
    num1 = 100
    num2 = 10
    num1 = "aaa"    ' ←間違って記載、ここではエラーにならない
                    '  ※ Variant型のため、代入ではエラーが起こらない
    MsgBox num1 + num2  ' ←ここでエラーになる
End Sub

【原因3】特定のオブジェクト型に異なる型を代入

変数の宣言時に型を指定したが、Setでオブジェクトを代入する際に宣言時と異なるオブジェクトを指定してしまうと本エラーが発生します。
例えば「Workbook型」で変数を宣言したが「Worksheet」型のオブジェクトを代入した、ということです。

例1:特定のオブジェクト型に異なる型を代入
   ※ 今回はWorkbook型の変数にWorksheetオブジェクトを代入

Sub ErrSample3()
    Dim wb As Workbook
    Set wb = ThisWorkbook.ActiveSheet   ' ActiveSheet は誤って記載
    MsgBox wb.Name
End Sub

【原因4】ワークシート関数でエラー

ワークシート関数がエラーが返して、変数に格納した場合、その変数を使用すると本エラーが生じる場合があります。

例1:ワークシート関数【VLookup関数】で検索値がなく、エラーが返ってきた

Sub ErrSample4()
    Dim cusName As Variant
    cusName = Application.VLookup("1", Range("A1:B10"), 2, False)
    Range("A1") = cusName & "様"  '←VLookupで検索値が範囲内に無い場合、ここでエラー
End Sub

補足ですが「Application.WorksheetFunction.VLookup("1", Range("A1:B10"), 2, False)」とすると VLookupでエラーが検索値が見つからなかった時点で「実行時エラー 1004」が発生します。

【特別編】論理エラーになりうるミス

論理エラーとは、正しい文法で実行できるが、期待した動作にならないエラーです。
本ページで後述しますが、Variant型を使用すると論理エラーが生じやすくなります。
極力、Long型や、Single型、String型等、肩を明確に指定しましょう。

例:Variant形に文字型(数値)を代入

Sub LogiErrSample()
    Dim val1 As Variant
    Dim val2 As Variant
    val1 = "100"
    val2 = "10"
    '110と表示させたかったが、10010と表示された
    MsgBox val1 + val2
End Sub

解決方法は?

IsError関数でエラーが返されたか確認する

IsError関数を使用すると、変数に格納されているデータがエラー値か確認することが出来ます。 Not(反転演算子)と、If文と組み合わせて「エラーでないとき」の処理が組めます。

例1:IsError関数の使用サンプル

Sub SolutionSample1()
    Dim cusName As Variant
    cusName = Application.VLookup(1, Range("A1:B10"), 2, False)
    ' エラーでない場合、真
    If Not IsError(cusName) Then
        ' エラーでない時の処理
        MsgBox cusName & "様"
    Else
        MsgBox "VLookupでエラーとなりました"
    End If
End Sub

このエラーの予防策

このエラーは修正に時間を要します。そのため、エラーが発生しないようにすることが非常に大事です。

型の変換は関数を使用して明確にする

vbaでは、数値型の変数に文字列"10"を代入しても、自動変換で10となります。 しかし、他人がこれを見たときにミスしているのか、自動変換で型変換される前提なのかがわかりません。
以下の関数で、変数の型データを明示的に変更が出来るので活用しましょう。

  • CStr関数 … 数値型や日付型・論理型等をString型に変換
  • CInt関数 … 数値・文字列等をInteger型に変換 ※1、※2
  • CLng関数 … 数値・文字列等をLong型に変換 ※1、※2
  • CSng関数 … 数値・文字列等をSingle型に変換
  • CDbl関数 … 数値・文字列等をDouble型に変換
  • CCur関数 … 数値・文字列等をCurrency型に変換

※1 小数がある場合、注意。例えば CLng(4.5)→4 となり、CLng(5.5)→6 となる。
  四捨五入でない。
※2 小数点以下の処理は、WorksheetFunction.Round(変数, 0) 等を使用すること。

例1:明示的な型の変換

Sub SolutionSample2()
    Dim num As Long
    Dim str As String
    num = 10
    str = CStr(num)
    MsgBox str + "1"    '101と表示される
End Sub

なお、「num = CInt("32768")」等、限界値を超えるとオーバーフローによるエラーが発生します。

IsNumeric関数/WorksheetFunction.IsNumberで、数値か確認する

例1:IsNumeric関数で数値か確認する
IsNumeric関数を使用すると、変数に格納されている値が数値であるかを返します。 数値である場合はTrue、数値でない場合はFalseを返すため、If文と併用することが多いです。

Sub SolutionSample3_1()
    Dim val As Variant
    val = "ABC"
    If IsNumeric(val) Then
        MsgBox "変数valは数値です"
    Else
        MsgBox "変数valは数値でありません"
    End If
End Sub

例2:IsNumeric関数の注意点
IsNumeric関数を使用する時、注意が必要です。文字列型の変数が、数値になりえる時(例:1, -1 等)は、文字列型の-1であっても、Trueを返します。

Sub SolutionSample3_2()
    Dim str As String
    str = "123.4"
    ' 中身は文字列だが、「True」を返してしまう
    MsgBox "変数str は数値か:" & IsNumeric(str)
End Sub

例3:WorksheetFunction.IsNumberで数値が確認する
WorksheetFunction.IsNumberを使用すると、文字列型の変数が、数値になりえる時(例:1, -1 等)でも「数値でないと」返ってきます。なお、IsNumeric関数より、やや遅めの処理となってしまうので、多用しないようにしましょう。

Sub SolutionSample3_3()
    Dim str As String
    str = "123.4"
    '「変数str は数値か:False」と表示される
    MsgBox "変数str は数値か:" & WorksheetFunction.IsNumber(str)
End Sub
VarType関数やTypeName関数で変数の型を確認する

VarType関数

VarType関数は作成された変数の型によって、異なる値を返します。
VarType関数専用の定数が定められており、変数がLong型なら(定数:vbLong/値:3)と定められています。

VarType関数の定数一覧表

定数型名
vbInteger2整数型(Integer)
vbLong3長整数型(Long)
vbSingle3単精度浮動小数点数(Single)
vbDouble5倍精度浮動小数点型(Double)
vbCurrency6通貨型(Currency)
vbDate7日付型(Date)
vbString8文字列型(String)
vbBoolean11ブーリアン型(Boolean)
vbVariant12Variant型(処理で変わる)

例1:VarType関数のサンプル

Sub SolutionSample4()
    Dim str As String
    If VarType(str) = vbString Then
        MsgBox "変数str は、String型です☆"
    End If
End Sub

TypeName関数

TypeName関数を使用すると、変数の型名を返してくれます。
Variantを除く、プリミティブ型(非オブジェクト型)は型の名前が返されます。
Variant型は代入されるまで"Empty"、代入後は値に応じた型名が返されます。
オブジェクト型は代入されるまで"Nothing"、代入後は値に応じた型名が返されます。

Sub SolutionSample5()
    Dim str As String
    Dim num As Long
    Dim val As Variant
    Dim wb As Workbook
    Debug.Print TypeName(str)   'String と表示される
    Debug.Print TypeName(num)   'Long と表示される
    Debug.Print TypeName(val)   'Empty と表示される
    Debug.Print TypeName(wb)    'Nothing と表示される
End Sub
Variant型の危険性

Variant型はプリミティブ型(値型≒非参照型)の変数以外、値を格納できる便利な変数です。 プログラム中、変数をLong型からString型に変更することもできます。
ですが、可読性が下がり、論理エラーが起こりやすくなります。仮に文字列"10"をVariant型の変数numに文字10を代入すると、IsNumericがTrue、TypeNameが文字列と動作が不安定になります。
代入予定の値が確定している場合は、キチンと型を定義しましょう。

Sub SolutionSample6()
    Dim val As Variant
    val = "10"
    Debug.Print IsNumeric(val)  ' True(=数値である)と返ってくる
    Debug.Print TypeName(val)   ' String(=文字列型)と返ってくる
End Sub

関連リンク

ページの先頭へ