엑셀 VBA 런타임 오류 13 해결: 형식이 일치하지 않습니다 원인 찾기

엑셀 VBA 코드를 실행할 때 다음 메시지가 표시될 수 있습니다.

런타임 오류 '13':
형식이 일치하지 않습니다.

이 오류는 코드가 숫자, 날짜, 문자열, 배열 또는 객체 중 특정 형식을 기대했지만 실제로는 다른 형식의 값이 전달됐을 때 발생합니다.

셀에 보이는 값만 확인해서는 원인을 찾기 어려울 수 있습니다. 숫자처럼 보이는 텍스트, 빈 문자열, #N/A 같은 Excel 오류 값, 여러 셀에서 반환된 배열, Range 객체가 서로 다른 방식으로 처리되기 때문입니다.

엑셀 VBA에서 셀 값과 변수 형식 불일치로 발생하는 런타임 오류 13을 설명하는 대표 개념 이미지
VBA 런타임 오류 13은 코드가 요구하는 데이터 형식과 실제 셀 값·변수·배열·객체의 형식이 맞지 않을 때 발생할 수 있습니다. 위 이미지는 오류 원인을 설명하기 위한 대표 개념 이미지입니다.

이 글은 Microsoft의 VBA Type mismatch 오류, IsError, IsNumeric, IsDate, 형식 변환 함수, Range.Value, Set 및 Option Explicit 공식 문서를 기준으로 작성했습니다. 예제의 시트 이름과 셀 범위는 실제 통합 문서에 맞게 변경해야 합니다.

오류 창에서 디버그를 눌러 멈춘 줄부터 확인합니다

런타임 오류 13 창에서 디버그를 누르면 VBA 편집기가 오류가 발생한 줄을 강조합니다.

강조된 줄 전체를 한꺼번에 바꾸기 전에 오른쪽 값이 실제로 어떤 형식인지 확인해야 합니다. 예를 들어 다음 줄이 강조됐다고 가정합니다.

quantity = ws.Cells(rowIndex, "B").Value2

왼쪽의 quantityLong인데 B열에 문자, Excel 오류 값 또는 정수로 변환할 수 없는 값이 들어 있으면 대입 과정에서 형식 불일치가 발생할 수 있습니다.

TypeName과 VarType으로 실제 형식을 확인합니다

셀에 보이는 표시 형식과 VBA가 받은 실제 데이터 형식은 다를 수 있습니다. 오류가 발생하는 줄 바로 앞에 값을 Variant로 받은 다음 TypeNameVarType을 출력하면 원인을 좁힐 수 있습니다.

Dim rawValue As Variant

rawValue = ws.Cells(rowIndex, "B").Value2

Debug.Print "주소: " & ws.Cells(rowIndex, "B").Address
Debug.Print "TypeName: " & TypeName(rawValue)
Debug.Print "VarType: " & CStr(VarType(rawValue))

VBA 편집기에서 보기 → 직접 실행 창을 열거나 Ctrl+G를 누르면 출력 결과를 확인할 수 있습니다.

확인 결과 의미 먼저 확인할 부분
String 문자열 또는 숫자처럼 보이는 텍스트 IsNumeric 검사 후 숫자 변환
Double·Integer·Long 숫자 값 대상 변수의 범위와 소수 처리
Date 날짜 또는 시간 값 IsDate 검사와 날짜 변환
Error #N/A, #VALUE!, #DIV/0! 같은 Excel 오류 값 IsError를 먼저 실행
Variant() 여러 셀에서 반환된 배열 행·열 인덱스로 배열 요소 접근
Range·Worksheet 등 값이 아니라 객체 Set 또는 .Value2 사용 구분

숫자 변수에 문자나 Excel 오류 값을 넣은 경우

다음 코드는 B2 값을 곧바로 Long 변수에 저장합니다.

Dim quantity As Long

quantity = Range("B2").Value2

B2가 정상적인 정수라면 대입할 수 있지만, “미입력” 같은 텍스트나 #N/A 같은 오류 값이면 Long으로 변환할 수 없습니다.

셀 값을 먼저 Variant로 받은 뒤 오류, 빈 값, 숫자 여부를 순서대로 확인하는 편이 안전합니다.

Dim rawValue As Variant
Dim quantity As Double

rawValue = Range("B2").Value2

If IsError(rawValue) Then
    MsgBox "B2에 Excel 오류 값이 있습니다.", vbExclamation

ElseIf IsEmpty(rawValue) Then
    MsgBox "B2가 비어 있습니다.", vbExclamation

ElseIf Len(Trim$(CStr(rawValue))) = 0 Then
    MsgBox "B2에 빈 문자열이 있습니다.", vbExclamation

ElseIf Not IsNumeric(rawValue) Then
    MsgBox "B2를 숫자로 변환할 수 없습니다.", vbExclamation

Else
    quantity = CDbl(rawValue)
    Debug.Print quantity
End If

IsNumeric은 식 전체를 숫자로 평가할 수 있으면 True, 그렇지 않으면 False를 반환합니다. 따라서 변환 함수를 실행하기 전에 값의 변환 가능 여부를 확인하는 용도로 사용할 수 있습니다.

#N/A는 문자열이 아니라 Excel 오류 값입니다

셀에 #N/A가 보이더라도 VBA가 받은 값은 일반 문자열 “#N/A”가 아닐 수 있습니다. 이 값을 문자열이나 숫자와 바로 비교하면 형식 불일치가 발생할 수 있습니다.

다음처럼 오류 값을 바로 문자열과 비교하지 않습니다.

' 오류 값이 들어 있으면 형식 불일치가 발생할 수 있음
If Range("A2").Value2 <> "#N/A" Then
    Debug.Print Range("A2").Value2
End If

먼저 IsError로 Excel 오류 값인지 확인한 뒤 정상 값만 비교합니다.

Dim cellValue As Variant

cellValue = Range("A2").Value2

If IsError(cellValue) Then
    Debug.Print "A2에 Excel 오류 값이 있습니다."

ElseIf CStr(cellValue) = "완료" Then
    Debug.Print "처리 완료"
End If
검사를 한 줄에 모두 넣지 않는 이유

VBA의 복합 조건은 다른 언어의 단락 평가 방식과 다르게 생각해야 합니다. 오류 값이 포함될 가능성이 있다면 IsError 검사와 실제 비교·변환을 중첩된 If 문으로 분리하는 편이 원인을 명확하게 보여줍니다.

날짜로 변환하기 전에 IsDate를 확인합니다

다음 코드는 A2가 유효한 날짜라는 전제에서 실행됩니다.

Dim orderDate As Date

orderDate = CDate(Range("A2").Value2)

A2에 날짜로 해석할 수 없는 텍스트나 Excel 오류 값이 있으면 변환 과정에서 오류가 발생할 수 있습니다. 오류 값과 날짜 가능 여부를 순서대로 확인합니다.

Dim rawDate As Variant
Dim orderDate As Date

rawDate = Range("A2").Value2

If IsError(rawDate) Then
    MsgBox "A2에 Excel 오류 값이 있습니다.", vbExclamation

ElseIf IsEmpty(rawDate) Then
    MsgBox "A2가 비어 있습니다.", vbExclamation

ElseIf Not IsDate(rawDate) Then
    MsgBox "A2를 날짜로 변환할 수 없습니다.", vbExclamation

Else
    orderDate = CDate(rawDate)
    Debug.Print Format$(orderDate, "yyyy-mm-dd")
End If

텍스트 날짜의 해석은 Windows의 지역 날짜 형식에 영향을 받을 수 있습니다. 원본 데이터가 여러 지역 형식을 섞어 사용한다면 문자열을 무조건 CDate로 변환하기보다 연도·월·일을 구분해 검증하는 방법을 검토해야 합니다.

여러 셀의 Value는 단일 값이 아니라 배열입니다

한 셀의 값을 읽으면 일반적으로 하나의 값이 반환되지만, 여러 셀로 구성된 범위의 Value 또는 Value2를 읽으면 2차원 Variant 배열이 반환됩니다.

다음 코드는 A2:C10의 전체 값을 배열로 받습니다.

Dim values As Variant

values = Range("A2:C10").Value2

Debug.Print TypeName(values)
Debug.Print values(1, 1)

배열 전체를 문자열이나 숫자 변수에 직접 넣거나 단일 값처럼 비교하면 형식 불일치가 발생할 수 있습니다.

Dim resultText As String

' 여러 셀의 결과는 배열이므로 String에 직접 대입하지 않음
resultText = Range("A2:C10").Value2

단일 값이 필요하면 한 셀만 지정합니다.

Dim resultValue As Variant

resultValue = Range("A2").Value2

여러 값이 필요하면 배열로 받은 뒤 행과 열 인덱스로 접근합니다.

Dim values As Variant
Dim rowIndex As Long
Dim columnIndex As Long

values = Range("A2:C10").Value2

For rowIndex = LBound(values, 1) To UBound(values, 1)
    For columnIndex = LBound(values, 2) To UBound(values, 2)

        If IsError(values(rowIndex, columnIndex)) Then
            Debug.Print "오류 값 위치: " & rowIndex & ", " & columnIndex
        Else
            Debug.Print values(rowIndex, columnIndex)
        End If

    Next columnIndex
Next rowIndex

Range 객체와 셀 값을 구분합니다

Range("A2")는 셀의 내용 자체가 아니라 Range 객체입니다. 객체 참조를 변수에 넣을 때는 Set을 사용하고, 셀 값이 필요하면 .Value2를 사용합니다.

Range 객체를 저장할 때:

Dim sourceCell As Range

Set sourceCell = Range("A2")

셀 값을 저장할 때:

Dim sourceValue As Variant

sourceValue = Range("A2").Value2

객체를 받은 뒤 문자열 값이 필요하다면 오류 여부를 먼저 확인합니다.

Dim sourceCell As Range
Dim sourceValue As Variant
Dim sourceText As String

Set sourceCell = Range("A2")
sourceValue = sourceCell.Value2

If IsError(sourceValue) Then
    MsgBox "A2에 Excel 오류 값이 있습니다.", vbExclamation
Else
    sourceText = CStr(sourceValue)
    Debug.Print sourceText
End If

형식 변환 함수는 검사가 끝난 뒤 사용합니다

VBA에는 값을 특정 형식으로 변환하는 함수가 있습니다.

함수 변환 결과 변환 전에 확인할 항목
CStr String IsError·IsNull
CLng Long 정수 IsError·IsNumeric·허용 범위
CDbl Double IsError·IsNumeric
CDate Date IsError·IsDate
CBool Boolean 원본 값의 의미와 허용 형식

변환 함수를 오류를 없애는 만능 처리로 사용하면 안 됩니다. 변환할 수 없는 문자열이나 Excel 오류 값을 전달하면 변환 함수 자체에서 다시 오류가 발생할 수 있습니다.

반복문에서 오류 13이 발생하는 행을 기록합니다

여러 행을 처리하는 매크로에서는 특정 행 하나에 문자나 오류 값이 섞여 있을 수 있습니다. 모든 오류를 무시하지 말고 문제가 있는 행을 별도로 표시하면 원본 데이터를 찾기 쉽습니다.

Option Explicit

Public Sub SumValidAmounts()

    Dim ws As Worksheet
    Dim lastRow As Long
    Dim rowIndex As Long
    Dim rawValue As Variant
    Dim totalAmount As Double

    Set ws = ThisWorkbook.Worksheets("데이터")

    lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row

    For rowIndex = 2 To lastRow

        rawValue = ws.Cells(rowIndex, "B").Value2

        If IsError(rawValue) Then

            ws.Cells(rowIndex, "C").Value = "Excel 오류 값"

        ElseIf IsEmpty(rawValue) Then

            ws.Cells(rowIndex, "C").Value = "빈 셀"

        ElseIf Len(Trim$(CStr(rawValue))) = 0 Then

            ws.Cells(rowIndex, "C").Value = "빈 문자열"

        ElseIf Not IsNumeric(rawValue) Then

            ws.Cells(rowIndex, "C").Value = "숫자가 아님"

        Else

            totalAmount = totalAmount + CDbl(rawValue)
            ws.Cells(rowIndex, "C").Value = "반영"

        End If

    Next rowIndex

    ws.Range("E2").Value = totalAmount

End Sub

위 코드는 오류가 있는 셀을 강제로 0으로 바꾸지 않습니다. B열 값을 검사한 뒤 C열에 제외 이유를 기록하고, 숫자로 확인된 값만 합계에 반영합니다.

실제 업무 규칙에 따라 빈 셀을 0으로 볼지, 실행을 중단할지, 별도 오류 목록에 기록할지는 코드에서 명시적으로 정해야 합니다.

On Error Resume Next로 전체 오류를 숨기지 않습니다

다음처럼 프로시저 처음부터 끝까지 On Error Resume Next를 적용하면 오류 13이 발생해도 코드가 다음 줄로 넘어갈 수 있습니다.

On Error Resume Next

quantity = Range("B2").Value2
total = total + quantity

이 방식은 형식이 잘못된 값이 어느 셀에서 들어왔는지 알기 어렵게 만들고, 이후 계산에 이전 값이나 초기값이 사용되는 문제를 남길 수 있습니다.

예상 가능한 셀 데이터 문제는 IsError, IsNumeric, IsDate, IsArray 같은 검사로 분기하고, 처리할 수 없는 오류는 명확하게 기록하거나 다시 발생시키는 편이 적절합니다.

Option Explicit로 변수 오타를 실행 전에 찾습니다

각 모듈 맨 위에 Option Explicit을 넣으면 사용한 변수를 명시적으로 선언해야 합니다.

Option Explicit

Public Sub Example()

    Dim quantity As Double

    quantity = 10

End Sub

선언하지 않은 변수나 변수 이름의 오타를 컴파일 단계에서 찾을 수 있으므로, 의도하지 않은 Variant 변수가 만들어지는 문제를 줄이는 데 도움이 됩니다.

VBA 편집기에서 도구 → 옵션 → 편집기변수 선언 요구를 선택하면 새 모듈에 Option Explicit이 자동으로 추가됩니다. 이미 작성된 기존 모듈에는 직접 추가해야 합니다.

오류 13을 찾는 순서

1. 디버그를 눌러 강조된 줄 확인
어떤 변수에 어떤 값이나 객체를 넣으려 했는지 확인합니다.
2. 오른쪽 값을 Variant로 분리
셀 값이나 함수 결과를 먼저 Variant 변수에 저장합니다.
3. TypeName·VarType 출력
String, Error, Date, Variant 배열 또는 객체 중 무엇인지 확인합니다.
4. Excel 오류 값을 먼저 분리
#N/A 등의 가능성이 있다면 비교나 변환보다 IsError를 먼저 실행합니다.
5. 변환 가능 여부 확인
숫자는 IsNumeric, 날짜는 IsDate로 확인한 뒤 CDbl·CLng·CDate 등을 사용합니다.
6. 단일 셀과 여러 셀 구분
여러 셀의 Value2는 배열이므로 행·열 인덱스로 값을 읽습니다.
7. 객체와 값을 구분
Range·Worksheet 객체에는 Set을 사용하고, 셀 내용이 필요하면 Value2를 사용합니다.

내용 확인에 사용한 Microsoft 공식 자료

공식 문서 확인일: 2026년 7월 28일

Post a Comment

다음 이전