Excelマクロの実行中に「実行時エラー ’13’: 型が一致しません」が表示されて処理が止まってしまう――このエラーはVBAにおいて非常に遭遇頻度が高く、原因がデータの中身に依存することが多いため、コードを見ただけでは気づきにくいのが特徴です。「昨日まで動いていたのに今日突然エラーになった」というケースの多くは、このエラー13が原因です。本記事では、数値・日付・文字列・セル値・オブジェクトといった場面ごとに、エラー13の原因と修正方法をコード付きで体系的に解説します。
目次
- 実行時エラー’13’とは何か
- 原因1:セルの値を変数に代入するときの型ミス
- 原因2:空白セル・エラー値セルの扱いミス
- 原因3:文字列を数値に変換するときの失敗
- 原因4:日付型の扱いミス
- 原因5:異なる型同士の比較・演算
- 原因6:オブジェクト変数への代入ミス
- 原因7:InputBoxやユーザーフォームからの入力値
- 型チェック・変換ユーティリティ関数集
- デバッグ手順:型を特定する方法
- エラーハンドリングテンプレート
- エラー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の発生を大幅に抑制できる
「型の検証は面倒」と感じるかもしれませんが、一度ユーティリティ関数を整備してしまえば、あとはそれを呼び出すだけです。安定したマクロを作るための投資として、ぜひ本記事のコードをそのまま活用してください。