Excelマクロの実行中に「実行時エラー ’13’: 型が一致しません」が表示されて処理が止まってしまう――このエラーはVBAにおいて非常に遭遇頻度が高く、原因がデータの中身に依存することが多いため、コードを見ただけでは気づきにくいのが特徴です。「昨日まで動いていたのに今日突然エラーになった」というケースの多くは、このエラー13が原因です。本記事では、数値・日付・文字列・セル値・オブジェクトといった場面ごとに、エラー13の原因と修正方法をコード付きで体系的に解説します。


目次


実行時エラー’13’とは何か

エラー13「型が一致しません(Type Mismatch)」は、変数や引数に期待される型と、実際に渡された値の型が合っていないときに発生するエラーです。VBAは型に厳格な言語であり、たとえば Long 型の変数に文字列 "abc" を代入しようとすると即座にこのエラーを投げます。

特に厄介なのは、Excelのセルから値を取得するケースです。セルには数値・文字列・日付・空白・エラー値(#N/Aなど)と様々な型が混在するため、「通常データは問題ないが、例外データが1行だけ混ざっていた」という状況で突然エラー13が発生します。主な発生パターンは次のとおりです。

  • 数値型変数にセルの文字列値(”-”や空欄など)を代入しようとした
  • 数値に変換できない文字列を CInt()CLng() に渡した
  • 日付型変数に日付として解釈できない文字列を代入しようとした
  • セルにエラー値(#N/A、#VALUE!など)が入っていてそのまま演算しようとした
  • 配列の要素型と異なる型の値を代入しようとした
  • Set をつけるべきオブジェクト変数に Set なしで代入しようとした(逆も同様)

原因1:セルの値を変数に代入するときの型ミス

最も多いパターンです。Excelのセルは見た目が数字でも、セルの書式や入力方法によって内部的に文字列として保持されていることがあります。これを数値型変数に代入しようとするとエラー13が発生します。

エラーが起きるコード例

' セルA1に文字列「100」や「-」や空欄が入っているとエラー13
Dim total As Long
total = ActiveSheet.Cells(1, 1).Value   ' → 実行時エラー '13'

' ループ中に1行でも想定外のデータがあると止まる
Dim i As Long
Dim score As Integer

For i = 1 To 100
    score = Cells(i, 3).Value   ' C列に "未入力" などの文字列があるとエラー13
Next i

修正後のコード

' ========================================
' セル値を安全に数値として取得するパターン
' ========================================
Sub SafeCellToNumber()

    Dim ws       As Worksheet
    Dim i        As Long
    Dim lastRow  As Long
    Dim score    As Double
    Dim cellVal  As Variant   ' まずVariantで受け取る

    Set ws = ThisWorkbook.Sheets(1)
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    Dim total As Double
    total = 0

    For i = 2 To lastRow   ' 1行目はヘッダーとしてスキップ

        cellVal = ws.Cells(i, 3).Value

        ' 空白・エラー値・非数値をスキップ
        If IsEmpty(cellVal) Then GoTo NextRow
        If IsError(cellVal) Then GoTo NextRow
        If Not IsNumeric(cellVal) Then
            Debug.Print i & "行目:数値ではありません [" & cellVal & "]"
            GoTo NextRow
        End If

        score = CDbl(cellVal)
        total = total + score

NextRow:
    Next i

    MsgBox "合計: " & total, vbInformation

End Sub

重要なポイント:セルから値を取得するときは、まず Variant 型で受け取ってから IsEmpty()IsError()IsNumeric() で検証し、安全であることを確認してから目的の型に変換するのが基本パターンです。


原因2:空白セル・エラー値セルの扱いミス

Excelシートには空白セルやワークシート関数のエラー値(#N/A、#VALUE!、#REF!など)が含まれることがあります。これらを型指定済みの変数に直接代入したり、そのまま演算に使うとエラー13が発生します。

エラーが起きるコード例

' 空白セルをLong型変数に代入(Emptyは数値として扱えない場合がある)
Dim val As Long
val = Cells(5, 1).Value   ' 空白セルの場合、0が入ることもあるが環境によってエラー13

' セルに #N/A などのエラー値が入っている場合
Dim price As Double
price = Cells(3, 2).Value * 1.1   ' → 実行時エラー '13'(エラー値は演算不可)

修正後のコード(IsEmpty・IsErrorで前処理)

' ========================================
' 空白・エラー値を安全に処理するパターン
' ========================================
Function GetNumericValue(cell As Range, _
                         Optional defaultValue As Double = 0) As Double

    Dim v As Variant
    v = cell.Value

    ' エラー値チェック(#N/A, #VALUE!, #REF! など)
    If IsError(v) Then
        GetNumericValue = defaultValue
        Exit Function
    End If

    ' 空白チェック
    If IsEmpty(v) Or Len(Trim(CStr(v))) = 0 Then
        GetNumericValue = defaultValue
        Exit Function
    End If

    ' 数値変換可能かチェック
    If IsNumeric(v) Then
        GetNumericValue = CDbl(v)
    Else
        GetNumericValue = defaultValue
    End If

End Function

' 使用例
Sub ProcessData()

    Dim ws      As Worksheet
    Dim i       As Long
    Dim lastRow As Long
    Dim price   As Double
    Dim qty     As Double

    Set ws = ThisWorkbook.Sheets(1)
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    For i = 2 To lastRow
        price = GetNumericValue(ws.Cells(i, 2), 0)   ' デフォルト0
        qty   = GetNumericValue(ws.Cells(i, 3), 0)

        ws.Cells(i, 4).Value = price * qty
    Next i

    MsgBox "処理完了", vbInformation

End Sub

セルのエラー値を種別ごとに判定する

' エラー値の種類を特定して対処を変える
Function DescribeCellError(cell As Range) As String

    If Not IsError(cell.Value) Then
        DescribeCellError = "エラーなし"
        Exit Function
    End If

    Select Case cell.Value
        Case CVErr(xlErrNull)    ' #NULL!
            DescribeCellError = "#NULL!:範囲の共通部分が存在しません"
        Case CVErr(xlErrDiv0)    ' #DIV/0!
            DescribeCellError = "#DIV/0!:ゼロ除算が発生しています"
        Case CVErr(xlErrValue)   ' #VALUE!
            DescribeCellError = "#VALUE!:数値が必要な場所に文字列があります"
        Case CVErr(xlErrRef)     ' #REF!
            DescribeCellError = "#REF!:無効なセル参照です"
        Case CVErr(xlErrName)    ' #NAME?
            DescribeCellError = "#NAME?:数式名が認識されません"
        Case CVErr(xlErrNum)     ' #NUM!
            DescribeCellError = "#NUM!:無効な数値です"
        Case CVErr(xlErrNA)      ' #N/A
            DescribeCellError = "#N/A:値が見つかりません"
        Case Else
            DescribeCellError = "不明なエラー値"
    End Select

End Function

' 使用例
Sub CheckErrorCells()
    Dim ws  As Worksheet
    Dim cel As Range

    Set ws = ThisWorkbook.Sheets(1)

    For Each cel In ws.UsedRange
        If IsError(cel.Value) Then
            Debug.Print cel.Address & ":" & DescribeCellError(cel)
        End If
    Next cel
End Sub

原因3:文字列を数値に変換するときの失敗

CInt()CLng()CDbl() などの型変換関数は、変換できない文字列を渡されるとエラー13を投げます。CSVから取り込んだデータや、ユーザーが手入力したデータに全角数字・カンマ・通貨記号・スペースが含まれている場合に特によく発生します。

エラーが起きるコード例

' 全角数字はそのままでは変換できない
Dim n As Long
n = CLng("123")    ' → 実行時エラー '13'

' カンマ区切りの数値文字列も変換できない
n = CLng("1,234")     ' → 実行時エラー '13'

' 通貨記号付き
n = CLng("¥1000")     ' → 実行時エラー '13'

' 先頭・末尾スペース(Trimしていない)
n = CInt(" 42 ")      ' → 環境によってエラー13

修正後のコード(正規化してから変換する)

' ========================================
' 文字列を安全に数値変換するユーティリティ
' ========================================
Function ToNumber(rawStr As String, Optional defaultVal As Double = 0) As Double

    Dim cleaned As String
    cleaned = rawStr

    ' 前後の空白を除去
    cleaned = Trim(cleaned)

    ' 全角数字・記号を半角に変換
    cleaned = StrConv(cleaned, vbNarrow)

    ' よくある不要文字を除去
    cleaned = Replace(cleaned, ",",  "")   ' カンマ区切り除去
    cleaned = Replace(cleaned, "¥",  "")   ' 円記号除去
    cleaned = Replace(cleaned, "$",  "")   ' ドル記号除去
    cleaned = Replace(cleaned, "%",  "")   ' パーセント除去
    cleaned = Replace(cleaned, " ",  "")   ' スペース除去
    cleaned = Replace(cleaned, "-", "-")  ' 全角マイナス→半角
    cleaned = Replace(cleaned, "−", "-")   ' 別パターンの全角マイナス

    ' 変換可能かチェックしてから変換
    If IsNumeric(cleaned) Then
        ToNumber = CDbl(cleaned)
    Else
        ToNumber = defaultVal
    End If

End Function

' 使用例
Sub ConvertTest()
    Debug.Print ToNumber("123")        ' → 123
    Debug.Print ToNumber("1,234")         ' → 1234
    Debug.Print ToNumber("¥5,000")        ' → 5000
    Debug.Print ToNumber("  42  ")        ' → 42
    Debug.Print ToNumber("未入力", -1)    ' → -1(デフォルト値)
End Sub

シート全体の文字列数値を一括で正規化する

' セル範囲の文字列数値を数値型に一括変換
Sub ConvertTextToNumber(targetRange As Range)

    Dim cel As Range

    For Each cel In targetRange
        If Not IsError(cel.Value) And Not IsEmpty(cel.Value) Then
            Dim cleaned As String
            cleaned = Trim(StrConv(CStr(cel.Value), vbNarrow))
            cleaned = Replace(cleaned, ",", "")

            If IsNumeric(cleaned) Then
                cel.Value         = CDbl(cleaned)
                cel.NumberFormat  = "#,##0"   ' 数値書式を適用
            End If
        End If
    Next cel

End Sub

' 使用例:B列の2行目から最終行まで変換
Sub RunConvert()
    Dim ws      As Worksheet
    Dim lastRow As Long

    Set ws = ThisWorkbook.Sheets(1)
    lastRow = ws.Cells(ws.Rows.Count, 2).End(xlUp).Row

    ConvertTextToNumber ws.Range("B2:B" & lastRow)
    MsgBox "変換完了", vbInformation
End Sub

原因4:日付型の扱いミス

VBAの Date 型変数に、日付として解釈できない文字列を代入しようとするとエラー13が発生します。また、Excelのセルに「2024/13/01」のような存在しない日付や、日付に見えない文字列が入っている場合も同様です。

エラーが起きるコード例

' 日付として解釈できない文字列をDate型変数に代入
Dim d As Date
d = CDate("2024/13/01")   ' 13月は存在しない → 実行時エラー '13'
d = CDate("令和6年1月")   ' 和暦はCDateで変換できない → エラー13
d = CDate("")              ' 空文字列 → エラー13
d = CDate("未設定")        ' 文字列 → エラー13

修正後のコード(IsDateで検証してから変換)

' ========================================
' 日付型を安全に扱うパターン
' ========================================
Function ToDateSafe(rawVal As Variant, _
                    Optional defaultDate As Date = #1/1/1900#) As Date

    ' 空白・エラー値は即デフォルト返却
    If IsEmpty(rawVal) Then
        ToDateSafe = defaultDate
        Exit Function
    End If
    If IsError(rawVal) Then
        ToDateSafe = defaultDate
        Exit Function
    End If

    ' すでにDate型なら直接返す
    If VarType(rawVal) = vbDate Then
        ToDateSafe = CDate(rawVal)
        Exit Function
    End If

    ' 文字列の場合はIsDateで検証してから変換
    Dim strVal As String
    strVal = Trim(CStr(rawVal))

    If IsDate(strVal) Then
        ToDateSafe = CDate(strVal)
    Else
        ToDateSafe = defaultDate
    End If

End Function

' 使用例
Sub DateProcessing()

    Dim ws      As Worksheet
    Dim i       As Long
    Dim lastRow As Long
    Dim d       As Date
    Dim cellVal As Variant

    Set ws = ThisWorkbook.Sheets(1)
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    For i = 2 To lastRow
        cellVal = ws.Cells(i, 4).Value   ' D列の日付を処理

        d = ToDateSafe(cellVal)

        ' デフォルト日付(1/1/1900)は未入力とみなしてスキップ
        If d = #1/1/1900# Then
            ws.Cells(i, 5).Value = "日付未入力"
        Else
            ws.Cells(i, 5).Value = Format(d, "yyyy年mm月dd日")
        End If
    Next i

    MsgBox "日付処理完了", vbInformation

End Sub

日付の計算でありがちなエラー13

' セルの値をそのまま日付計算に使うとエラー13の原因になる
' NG
Dim diffDays As Long
diffDays = DateDiff("d", Cells(1, 1).Value, Cells(1, 2).Value)
' → どちらかのセルが空欄や文字列だとエラー13

' OK
Dim startDate As Variant
Dim endDate   As Variant

startDate = Cells(1, 1).Value
endDate   = Cells(1, 2).Value

If IsDate(startDate) And IsDate(endDate) Then
    diffDays = DateDiff("d", CDate(startDate), CDate(endDate))
    Debug.Print "日数差: " & diffDays
Else
    Debug.Print "日付として解釈できないセルがあります"
End If

原因5:異なる型同士の比較・演算

VBAでは異なる型同士の比較や演算が自動的に型変換される場合もありますが、変換できない組み合わせではエラー13が発生します。特に Null 値が混入しているときに発生しやすいです。

エラーが起きるコード例

' Null値を含む演算
Dim v As Variant
v = Null

Dim result As Long
result = v + 10   ' Null + 数値 → 実行時エラー '13'

' Boolean変数に数値以外を代入
Dim flag As Boolean
flag = "Yes"   ' → 実行時エラー '13'("True"や"False"ならOK)

' 文字列同士を比較する際に型が混在
Dim a As Long
Dim b As String
a = 10
b = "20"

If a > b Then   ' LongとStringの比較 → エラー13になる場合がある
    Debug.Print "aが大きい"
End If

修正後のコード

' Nullチェックを必ず入れる
Dim v As Variant
v = Null

Dim result As Long
If IsNull(v) Then
    result = 0   ' Nullのときはデフォルト値を使う
Else
    result = CLng(v) + 10
End If

' Boolean変換は専用の判定を行う
Function ToBool(val As Variant, Optional defaultVal As Boolean = False) As Boolean

    If IsEmpty(val) Or IsNull(val) Then
        ToBool = defaultVal
        Exit Function
    End If

    Dim s As String
    s = Trim(LCase(CStr(val)))

    Select Case s
        Case "true", "1", "yes", "on", "有", "○", "◯"
            ToBool = True
        Case "false", "0", "no", "off", "無", "×", "-"
            ToBool = False
        Case Else
            ToBool = defaultVal
    End Select

End Function

' 型を揃えてから比較する
Dim a As Long
Dim b As Long
a = 10
b = CLng("20")   ' 比較前に型を揃える

If a > b Then
    Debug.Print "aが大きい"
Else
    Debug.Print "bが大きい"
End If

原因6:オブジェクト変数への代入ミス

VBAでオブジェクト(WorksheetやRangeなど)を変数に代入するときは Set キーワードが必要です。Set を忘れると「型が一致しません(エラー13)」が発生します。逆に、値型の変数に Set を使ってもエラーになります。

エラーが起きるコード例

' Setを忘れるとエラー13
Dim ws As Worksheet
ws = ThisWorkbook.Sheets(1)   ' → 実行時エラー '13'(Set が必要)

Dim rng As Range
rng = ActiveSheet.Range("A1:A10")   ' → 実行時エラー '13'(Set が必要)

' 値型変数にSetを使ってもエラー13
Dim total As Long
Set total = 100   ' → 実行時エラー '13'(Setは不要)

修正後のコード

' オブジェクト変数には必ずSetを使う
Dim ws  As Worksheet
Dim rng As Range

Set ws  = ThisWorkbook.Sheets(1)          ' ← Set が必要
Set rng = ActiveSheet.Range("A1:A10")     ' ← Set が必要

' 値型変数はSetを使わない
Dim total As Long
total = 100   ' ← Set は不要

' オブジェクト変数と値型変数の見分け方
' オブジェクト型(Setが必要):Worksheet, Workbook, Range, Chart,
'                              Collection, Object, 各Officeオブジェクトなど
' 値型(Setは不要):Long, Integer, Double, String, Boolean, Date, Variant

Variantを使うときのオブジェクト代入

' Variant型でオブジェクトを受け取るときもSetが必要
Dim v As Variant

' NG
v = ThisWorkbook.Sheets(1)   ' → エラー13

' OK(オブジェクトを代入するときはSetを使う)
Set v = ThisWorkbook.Sheets(1)

' 代入後、型を確認してから使う
If TypeName(v) = "Worksheet" Then
    Dim ws As Worksheet
    Set ws = v
    ws.Cells(1, 1).Value = "OK"
End If

原因7:InputBoxやユーザーフォームからの入力値

InputBox の戻り値は常に 文字列型 です。これを直接数値型変数に代入したり、キャンセル時の戻り値(空文字列)を変換しようとするとエラー13が発生します。

エラーが起きるコード例

' InputBoxの戻り値を直接数値型変数に代入
Dim count As Integer
count = InputBox("件数を入力してください")   ' → エラー13(文字列が返る)

' キャンセル時の空文字列を変換
Dim price As Double
Dim input As String
input = InputBox("価格を入力してください")
price = CDbl(input)   ' キャンセルされると input="" → エラー13

修正後のコード(安全なInputBox処理)

' ========================================
' 安全なInputBox入力処理パターン
' ========================================
Sub SafeInputBoxNumber()

    Dim userInput As String
    Dim result    As Double

    userInput = InputBox("数値を入力してください", "入力")

    ' キャンセルまたは空入力のチェック
    If userInput = "" Then
        MsgBox "入力がキャンセルされました。", vbInformation
        Exit Sub
    End If

    ' 全角→半角変換 + 数値チェック
    userInput = Trim(StrConv(userInput, vbNarrow))
    userInput = Replace(userInput, ",", "")

    If Not IsNumeric(userInput) Then
        MsgBox "数値を入力してください。入力値:[" & userInput & "]", vbExclamation
        Exit Sub
    End If

    result = CDbl(userInput)
    MsgBox "入力された値:" & result, vbInformation

End Sub
' Application.InputBox(Type:=1)で数値入力のみ受け付ける
Sub SafeInputBoxWithType()

    Dim result As Variant

    ' Type:=1 は数値のみ受け付ける(文字列を入力するとExcel側でエラーを出す)
    result = Application.InputBox( _
                Prompt:="数値を入力してください", _
                Title:="数値入力", _
                Type:=1)

    ' キャンセル時はFalseが返る
    If result = False Then
        MsgBox "キャンセルされました。", vbInformation
        Exit Sub
    End If

    ' result はすでに数値型になっている
    MsgBox "入力値:" & result & vbCrLf & _
           "型:" & TypeName(result), vbInformation

End Sub

Application.InputBox の Type引数早見表

  • Type:=0:数式
  • Type:=1:数値
  • Type:=2:文字列
  • Type:=4:論理値(TrueまたはFalse)
  • Type:=8:セル参照(Rangeオブジェクト)
  • Type:=16:エラー値
  • Type:=64:値の配列

型チェック・変換ユーティリティ関数集

エラー13対策として汎用的に使えるユーティリティ関数をまとめました。標準モジュールに追加しておくと、プロジェクト全体で再利用できます。

' ========================================
' エラー13対策 型チェック・変換ユーティリティ集
' ========================================

' ----- 安全な数値変換 -----
Function ToDouble(v As Variant, Optional def As Double = 0) As Double
    If IsEmpty(v) Or IsNull(v) Or IsError(v) Then
        ToDouble = def : Exit Function
    End If
    Dim s As String
    s = Trim(StrConv(CStr(v), vbNarrow))
    s = Replace(Replace(Replace(s, ",", ""), "¥", ""), "$", "")
    s = Replace(s, "-", "-")
    ToDouble = IIf(IsNumeric(s), CDbl(s), def)
End Function

' ----- 安全な整数変換 -----
Function ToLong(v As Variant, Optional def As Long = 0) As Long
    ToLong = CLng(ToDouble(v, CDbl(def)))
End Function

' ----- 安全な文字列変換 -----
Function ToStr(v As Variant, Optional def As String = "") As String
    If IsEmpty(v) Or IsNull(v) Or IsError(v) Then
        ToStr = def : Exit Function
    End If
    ToStr = CStr(v)
End Function

' ----- 安全な日付変換 -----
Function ToDate(v As Variant, Optional def As Date = #1/1/1900#) As Date
    If IsEmpty(v) Or IsNull(v) Or IsError(v) Then
        ToDate = def : Exit Function
    End If
    If VarType(v) = vbDate Then ToDate = CDate(v) : Exit Function
    If IsDate(CStr(v)) Then
        ToDate = CDate(CStr(v))
    Else
        ToDate = def
    End If
End Function

' ----- 型名を返す(デバッグ用) -----
Function GetTypeName(v As Variant) As String
    If IsEmpty(v)  Then GetTypeName = "Empty"  : Exit Function
    If IsNull(v)   Then GetTypeName = "Null"   : Exit Function
    If IsError(v)  Then GetTypeName = "Error:" & CStr(v) : Exit Function
    GetTypeName = TypeName(v)
End Function

' ----- 使用例 -----
Sub UtilityTest()
    Debug.Print ToDouble("1,234.5")       ' → 1234.5
    Debug.Print ToDouble("未入力", -1)    ' → -1
    Debug.Print ToLong("42.8")            ' → 43(四捨五入)
    Debug.Print ToStr(Empty, "(なし)")    ' → (なし)
    Debug.Print ToDate("2024/06/01")      ' → 2024/06/01
    Debug.Print GetTypeName(Null)         ' → Null
    Debug.Print GetTypeName(42)           ' → Integer
    Debug.Print GetTypeName(Now())        ' → Date
End Sub

デバッグ手順:型を特定する方法

エラー13が発生したとき、「どのセル・変数がどんな型を持っているか」を素早く特定する方法を解説します。

ステップ1:エラー行でTypeNameとVarTypeを確認する

' エラーが起きる行の前にデバッグ出力を追加して型を確認
Dim v As Variant
v = ActiveSheet.Cells(1, 1).Value

' TypeNameで型の名前を確認
Debug.Print "TypeName: " & TypeName(v)
' 例: "String", "Double", "Long", "Date", "Boolean", "Empty", "Error"

' VarTypeで型番号を確認
Debug.Print "VarType: " & VarType(v)
' 主な値: 0=Empty, 1=Null, 2=Integer, 3=Long, 4=Single,
'         5=Double, 7=Date, 8=String, 11=Boolean, 17=Byte

ステップ2:シート上の問題データを特定する

' 指定範囲で数値でないセルを洗い出す
Sub FindNonNumericCells()

    Dim ws      As Worksheet
    Dim cel     As Range
    Dim report  As String
    Dim count   As Long

    Set ws = ThisWorkbook.Sheets(1)
    report = "数値でないセル一覧:" & vbCrLf
    count = 0

    For Each cel In ws.Range("B2:B100")
        Dim v As Variant
        v = cel.Value

        If IsError(v) Then
            report = report & cel.Address & ": エラー値 [" & DescribeCellError(cel) & "]" & vbCrLf
            count = count + 1
        ElseIf IsEmpty(v) Then
            ' 空白は無視
        ElseIf Not IsNumeric(v) Then
            report = report & cel.Address & ": 文字列 [" & CStr(v) & "]  型:" & TypeName(v) & vbCrLf
            count = count + 1
        End If
    Next cel

    If count = 0 Then
        MsgBox "問題のあるセルは見つかりませんでした。", vbInformation
    Else
        MsgBox report, vbExclamation
    End If

End Sub

ステップ3:On Error Resume Nextで問題行を特定する

' ループ中のどの行でエラーが出るかを特定する
Sub FindErrorRow()

    Dim ws      As Worksheet
    Dim i       As Long
    Dim lastRow As Long
    Dim total   As Double
    Dim errRows As String

    Set ws = ThisWorkbook.Sheets(1)
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    For i = 2 To lastRow
        On Error Resume Next
        total = total + CDbl(ws.Cells(i, 2).Value)

        If Err.Number = 13 Then
            errRows = errRows & i & "行目 [" & ws.Cells(i, 2).Value & "]" & vbCrLf
            Err.Clear
        End If
        On Error GoTo 0
    Next i

    If Len(errRows) > 0 Then
        MsgBox "以下の行でエラー13が発生しました:" & vbCrLf & errRows, vbExclamation
    Else
        MsgBox "問題なし。合計=" & total, vbInformation
    End If

End Sub

エラーハンドリングテンプレート

エラー13を含む型エラーに対応した、実務向けの標準エラーハンドリングテンプレートです。

' ========================================
' エラー13対応エラーハンドリングテンプレート
' ========================================
Sub MainWithTypeErrorHandling()

    Application.ScreenUpdating = False
    Application.Calculation    = xlCalculationManual
    Application.EnableEvents   = False

    On Error GoTo ErrorHandler

    ' ===== メイン処理 =====
    Dim ws      As Worksheet
    Dim i       As Long
    Dim lastRow As Long
    Dim val     As Variant

    Set ws  = ThisWorkbook.Sheets(1)
    lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row

    For i = 2 To lastRow
        val = ws.Cells(i, 2).Value

        If IsError(val) Or IsEmpty(val) Then GoTo NextRow

        ws.Cells(i, 3).Value = ToDouble(val) * 1.1

NextRow:
    Next i
    ' =====================

    Application.ScreenUpdating = True
    Application.Calculation    = xlCalculationAutomatic
    Application.EnableEvents   = True
    MsgBox "処理完了", vbInformation
    Exit Sub

ErrorHandler:
    Application.ScreenUpdating = True
    Application.Calculation    = xlCalculationAutomatic
    Application.EnableEvents   = True

    Dim msg As String

    Select Case Err.Number
        Case 13
            msg = "型が一致しません(エラー13)。" & vbCrLf & vbCrLf & _
                  "確認してください:" & vbCrLf & _
                  "・セルに数値以外の値が入っていないか" & vbCrLf & _
                  "・空白セルやエラー値(#N/Aなど)を処理しようとしていないか" & vbCrLf & _
                  "・Setキーワードの付け忘れ・付けすぎがないか"
        Case 9
            msg = "添字が有効範囲にありません(エラー9)。" & vbCrLf & _
                  "シート名・配列の添字を確認してください。"
        Case 1004
            msg = "Excelオブジェクトへの操作が失敗しました(エラー1004)。" & vbCrLf & _
                  "シート保護・ファイルパス・セル範囲を確認してください。"
        Case Else
            msg = "予期しないエラーが発生しました。"
    End Select

    MsgBox msg & vbCrLf & vbCrLf & _
           "エラー番号:" & Err.Number & vbCrLf & _
           "内容:" & Err.Description, _
           vbCritical, "実行時エラー " & Err.Number

End Sub

エラー13 原因チェックリスト

エラー13が発生したとき、以下のリストを上から順番に確認してください。多くの場合、このリストで原因を特定できます。

  • 数値型変数にセル値を代入する前に、IsNumeric() で数値チェックを行っているか
  • 空白セルに対して IsEmpty() のチェックを入れているか
  • セルにエラー値(#N/A・#VALUE!など)が入っていないか(IsError() で確認)
  • CInt()CLng()CDbl() に渡す文字列に全角数字・カンマ・通貨記号・スペースが含まれていないか
  • 日付型変数への代入前に IsDate() で検証しているか
  • 計算式に Nullが混入していないか(IsNull() でチェック)
  • オブジェクト変数(Worksheet・Range など)への代入に Set キーワードを使っているか
  • 値型変数(Long・String など)に誤って Set を使っていない
  • InputBox の戻り値を数値型変数に直接代入していないか(IsNumeric() チェック必須)
  • 比較・演算を行う変数同士の型が一致しているか(TypeName・VarTypeで確認)
  • Boolean型変数に渡す文字列が “True”・”False” または “1”・”0″ になっているか
  • ループ処理で途中のデータが想定外の型・内容になっていないか(FindNonNumericCellsで事前確認)

まとめ

実行時エラー’13’「型が一致しません」は、変数に渡す値の型が期待と異なるときに発生します。特にExcelのセルから値を取得する場面では、空白・エラー値・文字列数値・全角文字など想定外のデータが混在しやすく、「昨日まで動いていたのに」という突然のエラーにつながります。本記事の要点をまとめると次のとおりです。

  • セル値は必ず Variant で受け取りIsEmpty()IsError()IsNumeric() で検証してから型変換する
  • 文字列数値の変換は StrConv() で全角→半角変換し、カンマ・通貨記号を除去してから CDbl() に渡す
  • 日付は IsDate() で検証してから CDate() で変換する
  • Null 値は IsNull() で、エラー値は IsError() でガードしてから演算に使う
  • オブジェクト変数には必ず Set を使い、値型変数に Set を使わない
  • InputBox の戻り値は文字列であることを前提に、IsNumeric() で検証してから数値変換する
  • 本記事のユーティリティ関数集(ToDouble / ToLong / ToStr / ToDate)を標準モジュールに追加しておくと、プロジェクト全体でエラー13の発生を大幅に抑制できる

「型の検証は面倒」と感じるかもしれませんが、一度ユーティリティ関数を整備してしまえば、あとはそれを呼び出すだけです。安定したマクロを作るための投資として、ぜひ本記事のコードをそのまま活用してください。