TL;DR — Todo
Variantlleva una etiqueta de tipo.VarTypela devuelve como número (vbDoublees 5,vbStringes 8), yTypeNamela devuelve como palabra ("Double","String","Range"). En Excel, la etiqueta del valor de una celda la pone la celda, no tu código: un número entero llega comoDouble, un número con formato de moneda comoCurrencyredondeado a cuatro decimales, uno con formato de fecha comoDate, un error comoError, y un rango de varias celdas como una matriz. Pregunta por la etiqueta en los bordes de tu código, donde los valores llegan de celdas, de la selección del usuario o de un parámetroVariant, y declara tipos reales en todo lo demás.
Debug.Print TypeName(Range("A1").Value) ' Double, String, Date, Boolean, Error, Empty...
Debug.Print VarType(Range("A1").Value) ' 5, 8, 7, 11, 10, 0...
Debug.Print TypeName(Selection) ' Range, o ChartArea, Rectangle, Picture...
Este es el segundo artículo de una serie sobre preguntarle a un valor qué es: IsEmpty
comprueba una sola etiqueta, aquí VarType y TypeName leen cualquier etiqueta, e IsNull
comprueba la etiqueta que significa «mixto o desconocido». La idea de la serie es que un valor de VBA lleva
una etiqueta de tipo aparte de su contenido, y estas funciones leen la etiqueta, no el aspecto del valor.
Lo que aprenderás
- El modelo mental: la etiqueta la pone la celda, no tu código
- Constantes de VarType y cadenas de TypeName
- Por qué un número entero es un Double, y un formato de moneda redondea tus datos
- VarType mira a través de los objetos; TypeName los nombra
- La trampa de la matriz: una celda frente a varias
- Comprobar qué ha seleccionado el usuario
- Dónde preguntar, y dónde declarar en su lugar
El modelo mental: la etiqueta la pone la celda, no tu código
Cuando escribes Dim total As Double, el tipo lo decides tú. Cuando lees Range("A1").Value, no: Excel te
entrega un Variant, y lo que hay dentro lo decide la celda. La misma línea de código recibe un número en una
fila, texto en la siguiente, un error en la tercera y nada en la cuarta.
VarType y TypeName te dejan ver esa decisión antes de actuar sobre ella. No convierten nada y nunca fallan:
solo informan de la etiqueta.
Constantes de VarType y cadenas de TypeName
Las etiquetas que encontrarás al trabajar con Excel, con sus dos nombres:
| Celda o valor | VarType |
constante | TypeName |
|---|---|---|---|
| celda sin tocar | 0 | vbEmpty |
"Empty" |
| mixto o desconocido | 1 | vbNull |
"Null" |
| cualquier número, incluido 42 | 5 | vbDouble |
"Double" |
| número con formato de moneda | 6 | vbCurrency |
"Currency" |
| número con formato de fecha | 7 | vbDate |
"Date" |
| texto | 8 | vbString |
"String" |
#N/A, #DIV/0! y otros errores |
10 | vbError |
"Error" |
| VERDADERO o FALSO | 11 | vbBoolean |
"Boolean" |
| el valor de un rango de varias celdas | 8204 | vbArray + vbVariant |
"Variant()" |
Una variable Long da 3 (vbLong), una Integer da 2, y una variable de objeto da "Range", "Worksheet",
"Workbook" o "Nothing" con TypeName. TypeName siempre devuelve el nombre en inglés, en cualquier idioma
de Office, así que es seguro compararlo con una cadena.
La forma natural de usar la etiqueta es un Select Case que trate cada clase de celda:
Sub DescribeCell(ByVal c As Range)
Dim v As Variant
v = c.Value
Select Case VarType(v)
Case vbEmpty: Debug.Print c.Address, "empty"
Case vbString: Debug.Print c.Address, "text: " & v
Case vbDouble, vbCurrency: Debug.Print c.Address, "number: " & v
Case vbDate: Debug.Print c.Address, "date: " & Format$(v, "yyyy-mm-dd")
Case vbBoolean: Debug.Print c.Address, "logical: " & v
Case vbError: Debug.Print c.Address, "error: " & c.Text
End Select
End Sub
Por qué un número entero es un Double, y un formato de moneda redondea tus datos
Dos sorpresas salen del mismo hecho: Excel guarda todos los números como Double, y .Value los viste según el
formato de la celda.
Un número entero es un Double. Una celda que contiene 42 devuelve vbDouble, no vbLong. El código que
comprueba If VarType(c.Value) = vbLong nunca coincide con una celda. Para preguntar «¿es un número entero?»,
comprueba primero la etiqueta y después el valor, en dos pasos, porque el And de VBA evalúa los dos lados e
Int falla con texto: If VarType(v) = vbDouble Then isWhole = (v = Int(v)).
El formato cambia la etiqueta. Si una celda tiene formato de moneda, .Value devuelve un Currency; si
tiene formato de fecha, devuelve un Date. Un compañero que cambia el formato de una columna cambia lo que
recibe tu código, sin tocar un solo valor. Además, Currency solo guarda cuatro decimales, así que una celda con
formato de moneda que contiene un tipo de cambio de 1,234567 se lee como 1,2346.
.Value2 no aplica ese disfraz: devuelve un Double para números, fechas y moneda por igual, con toda la
precisión. En código de cálculo, lee .Value2:
Debug.Print TypeName(Range("B2").Value) ' Currency (B2 con formato $)
Debug.Print TypeName(Range("B2").Value2) ' Double
La guía de Value2 trata el lado de las fechas de esa misma diferencia.
VarType mira a través de los objetos; TypeName los nombra
Pasa el propio Range, no su valor, y las dos funciones discrepan:
Debug.Print TypeName(Range("A1")) ' Range
Debug.Print VarType(Range("A1")) ' 5 si A1 contiene un numero, no vbObject
VarType mira a través de un objeto que tiene propiedad predeterminada e informa del tipo de esa propiedad. La
propiedad predeterminada de un Range es su valor, así que VarType(Range("A1")) describe el contenido de la
celda, y solo un objeto sin propiedad predeterminada devuelve vbObject (9). TypeName informa del objeto en
sí.
Así que la regla es sencilla: usa TypeName (o TypeOf) para preguntar qué es un objeto, y VarType para
preguntar qué es un valor.
La trampa de la matriz: una celda frente a varias
Leer un rango en un Variant es la forma rápida de procesar datos, y esconde una trampa:
Dim data As Variant
data = Range("A2:A" & lastRow).Value
Debug.Print data(1, 1) ' Run-time error 13 cuando lastRow = 2
Cuando el rango tiene más de una celda, data es una matriz bidimensional. Cuando lastRow es 2 y el rango es
una sola celda, data es simplemente el valor de esa celda, e indexarlo falla con el error 13, Type mismatch
(«No coinciden los tipos» en un Excel en español). Los informes funcionan durante meses y fallan el día en que
solo hay una fila.
Compruébalo con IsArray y envuelve tú mismo el valor único:
If Not IsArray(data) Then
Dim one(1 To 1, 1 To 1) As Variant
one(1, 1) = data
data = one
End If
IsArray(v) es la misma prueba que (VarType(v) And vbArray) <> 0. La guía de matrices
trata la lectura de rangos en matrices.
Comprobar qué ha seleccionado el usuario
El uso real más habitual de TypeName es una protección al principio de una macro que trabaja con la selección.
Puede que el usuario haya hecho clic en un gráfico, una forma o una imagen en lugar de en celdas:
Sub FormatSelectedCells()
If TypeName(Selection) <> "Range" Then
MsgBox "Select some cells first."
Exit Sub
End If
Selection.NumberFormat = "#,##0.00"
End Sub
Sin la protección, Selection.NumberFormat lanza el error 438 (Object doesn't support this property or
method, «El objeto no admite esta propiedad o método» en un Excel en español) cuando hay un gráfico
seleccionado. If Not TypeOf Selection Is Range Then hace la misma comprobación, y el compilador detecta una
errata en Range, cosa que no puede hacer con la cadena "Range". Usa TypeOf en la lógica y TypeName
cuando quieras mostrar o registrar el nombre. La guía de Selection cubre el resto.
La decisión de criterio: pregunta en los bordes, declara en todo lo demás
VarType y TypeName son controles fronterizos. Úsalos donde los valores entran en tu código desde fuera: el
valor de una celda, la selección del usuario, un parámetro Variant, un elemento de una Collection, el
resultado de Application.Match. Dentro de tu propio código, declara Long, String, Double y Range, y
deja que el compilador haga las comprobaciones.
Si encuentras comprobaciones con VarType repartidas por el centro de una macro, el arreglo de verdad es leer
cada valor una vez, comprobar su etiqueta una vez en la frontera y convertirlo allí en una variable declarada.
Un único Select Case VarType a la entrada es más claro y más rápido que una docena de comprobaciones
If TypeName más adentro.
Cómo ayuda ExcelMaster
Las sorpresas de tipo vienen de los datos, no del código: una columna a la que se le puso formato de moneda, una
búsqueda que devuelve #N/A, un filtro que deja una sola fila.
ExcelMaster lee las celdas, los formatos y los errores reales de tu libro antes de escribir el código, para que la macro maneje los tipos que tu hoja contiene de verdad, incluido el caso de una sola fila y las filas con error.
Preguntas frecuentes
¿Qué diferencia hay entre VarType y TypeName en VBA?
VarType devuelve el tipo como número, por ejemplo 5 para Double u 8 para String. TypeName lo devuelve como
palabra, por ejemplo "Double" o "Range". Con objetos, TypeName nombra el objeto, mientras que VarType
informa del tipo de su propiedad predeterminada.
¿Cómo compruebo el tipo de dato de una celda en VBA?
Usa TypeName(Range("A1").Value) o VarType(Range("A1").Value). Un número devuelve Double; un texto, String;
un número con formato de fecha, Date; uno con formato de moneda, Currency; un error, Error; y una celda sin
tocar, Empty.
¿Por qué VarType devuelve Double para un número entero?
Excel guarda todos los números como Double, así que una celda que contiene 42 devuelve vbDouble. Para
comprobar si es un número entero, prueba v = Int(v) después de confirmar que el valor es numérico.
¿Cómo compruebo si la selección es un rango en VBA?
Usa If TypeName(Selection) = "Range" Then o If TypeOf Selection Is Range Then. Si hay un gráfico o una
forma seleccionados, TypeName devuelve en su lugar el nombre de ese objeto.
¿Qué significa VarType 8204?
8204 es vbArray + vbVariant (8192 + 12): una matriz de Variants. Es lo que obtienes del valor de un rango de
varias celdas.
Probado en
Probado en: Excel 365 (Windows 11), VBA 7.1 — última verificación el 04/10/2026.
Guías relacionadas: VBA IsEmpty · VBA IsNull · VBA Data Types · VBA Value2 · VBA Array · VBA Selection · VBA Select Case · VBA IsNumeric
