TL;DR — Un class module es un plano para tu propio tipo de objeto. Lo escribes una vez y luego creas tantas instancias independientes como quieras con
New. Dos cosas pillan a todo el mundo: el nombre del class module es el nombre del tipo (no hay ninguna palabra claveClassdentro) y los objetos son tipos de referencia, así queSet b = ahace deaybdos nombres para la misma instancia. Prefiere el explícitoSet x = New clsThingfrente aDim x As New clsThing, que esconde una trampa de instanciación perezosa.
' --- En un class module llamado clsEmployee (renómbralo en la ventana Propiedades) ---
Private mName As String
Private mSalary As Currency
Public Property Get Name() As String: Name = mName: End Property
Public Property Let Name(v As String): mName = v: End Property
Public Property Get Salary() As Currency: Salary = mSalary: End Property
Public Property Let Salary(v As Currency): mSalary = v: End Property
Public Function AnnualCost() As Currency ' el comportamiento vive junto a los datos
AnnualCost = mSalary * 1.3 ' salario + 30% de gastos generales
End Function
' --- En un módulo normal ---
Sub Demo()
Dim e As clsEmployee
Set e = New clsEmployee ' crea una instancia
e.Name = "Sarah"
e.Salary = 65000
MsgBox e.Name & " costs " & e.AnnualCost ' 84500
End Sub
Un Type agrupa campos. Un class module va un paso más allá:
agrupa campos y el código que actúa sobre ellos, y te da un objeto de verdad que puedes
crear, del que puedes copiar referencias y que puedes guardar en una
Collection. Es lo más cerca que VBA llega de la programación
orientada a objetos —y, bien usado, convierte un desparrame de variables sueltas y Sub
auxiliares en un puñado de objetos autónomos.
Lo que aprenderás
- El modelo mental — un plano del que estampas instancias
- Por qué no hay ninguna palabra clave
Class(el nombre del módulo es el tipo) - Crear instancias —
Set ... = Newy la trampa deAs New - La regla que sorprende a todo el mundo — los objetos comparten, no copian
- Preparación y limpieza —
Class_Initializey el constructor que falta - Cuándo una clase gana a un
Typeo a unaCollection
El modelo mental: un plano, no el edificio
Un class module es un plano; cada New construye una instancia a partir de él.
El plano clsEmployee describe lo que cada objeto empleado tiene (un nombre, un
salario) y hace (AnnualCost). No es en sí mismo un empleado —es el plano—. Set e = New clsEmployee construye un empleado real con sus propios datos; hazlo tres veces y
tendrás tres objetos independientes, cada uno con su propio nombre y salario, todos
construidos a partir del mismo plano.
Aférrate a esa distinción. Casi toda confusión con los class module —«¿por qué no hay
ningún nombre en la clase?», «¿por qué editar un objeto cambió otro?»— se disuelve en
cuanto separas el plano (la clase) de una instancia (un objeto New).
Por qué no hay ninguna palabra clave Class
Al venir de otros lenguajes, la gente abre un class module y busca una línea como Class clsEmployee. No existe, y teclearla es un error de compilación. En VBA, el nombre del
class module es el nombre del tipo. Cambias el nombre del tipo de objeto renombrando
el módulo en la ventana Propiedades (F4), no con una palabra clave en el código.
Así que el flujo es: inserta un class module, pulsa F4, pon (Name) a
clsEmployee (el prefijo cls es la convención habitual) y empieza a declarar sus
miembros directamente. El archivo es la clase; su nombre es el tipo que escribes
después de As.
Crear instancias: Set = New y la trampa de As New
Hay dos formas de crear un objeto, y no son equivalentes:
' Explícito (recomendado)
Dim e As clsEmployee
Set e = New clsEmployee ' creado exactamente aquí, en esta línea
' Auto-instanciar (parece más ordenado, esconde dos trampas)
Dim e As New clsEmployee ' AÚN NO creado — se crea en el primer uso
La forma As New es seductora porque es una sola línea, pero esconde dos problemas de
verdad:
- Nunca puedes comprobar
If e Is Nothing. ConAs New, en cuanto tocasepara comprobarlo, VBA lo instancia —así queIs Nothinges, en la práctica, siempreFalse—. Pierdes la capacidad de preguntar «¿se llegó a crear esto alguna vez?». - Se resucita a sí mismo. Pon una variable
As NewaNothing, vuelve a referenciarla y VBA crea en silencio una nueva instancia —un objeto zombi que reaparece cuando creías haberlo destruido—.
Regla: prefiere Dim e As clsEmployee + Set e = New clsEmployee. Crea el objeto en
una línea predecible y mantiene Is Nothing con sentido para que puedas protegerte de
objetos sin inicializar. Y nunca olvides el Set: escribir e = New clsEmployee sin él
lanza el error 91, «Variable de objeto o variable de bloque With no establecida» —la
misma regla de valor frente a objeto que dice que los objetos se
asignan con Set, no con =.
La regla que sorprende a todo el mundo: los objetos comparten, no copian
Esto es la imagen especular del artículo sobre Type, y es la fuente
más profunda de errores con los class module. Un objeto es un tipo de referencia.
Set b = a no copia el objeto —copia la referencia, así que a y b ahora
apuntan a la misma instancia:
Dim a As clsEmployee, b As clsEmployee
Set a = New clsEmployee
a.Salary = 50000
Set b = a ' ambos nombres -> UNA instancia
b.Salary = 70000 ' edita el objeto compartido
Debug.Print a.Salary ' 70000 — a «cambió sola»
Si de verdad querías dos empleados independientes, Set b = a es un error. VBA no
tiene copia automática para los objetos; escribes un método Clone que devuelve una
instancia nueva con los mismos valores de los campos. Y si lo que en realidad querías
desde el principio era copiar al asignar, esa es tu señal de que un
Type —un tipo de valor— era el mejor modelo. Saber qué semántica
necesitas, compartir o copiar, es toda la razón para entender ambas.
Preparación y limpieza: Class_Initialize y el constructor que falta
Una clase puede ejecutar código automáticamente cuando una instancia nace o muere:
Private Sub Class_Initialize() ' se ejecuta en Set e = New clsEmployee
mSalary = 0 ' pon aquí los valores predeterminados
End Sub
Private Sub Class_Terminate() ' se ejecuta cuando desaparece la última referencia
' cierra archivos, libera manejadores, etc.
End Sub
La pega: Class_Initialize no admite argumentos. VBA no tiene constructor con
parámetros —no puedes escribir New clsEmployee("Sarah", 65000)—. Primero creas el
objeto y luego fijas sus propiedades. Como ese baile en dos pasos es tedioso y fácil de
olvidar, la solución habitual es una pequeña función de fábrica en un módulo normal:
Function NewEmployee(nm As String, sal As Currency) As clsEmployee
Dim e As clsEmployee
Set e = New clsEmployee
e.Name = nm
e.Salary = sal
Set NewEmployee = e
End Function
' Set e = NewEmployee("Sarah", 65000) ' una línea legible
Mi regla general: cualquier clase que crees más de una o dos veces merece una función
de fábrica. Te da el constructor con parámetros que VBA se dejó fuera y mantiene la
creación en un solo sitio en lugar de en líneas de Set + propiedades desperdigadas.
Cuándo una clase gana a un Type o a una Collection
Recurre a un class module cuando al menos una de estas cosas sea cierta:
- Datos y comportamiento van juntos — el registro debería validar, dar formato o
calcular cosas sobre sí mismo, no tener esa lógica desperdigada por
Subauxiliares. - Necesitas muchos objetos independientes que se gestionan solos —pedidos, facturas, empleados—, idealmente guardados en una Collection, que acepta objetos pero no un Type.
- Quieres ocultar los detalles internos — expón una superficie limpia a través de
propiedades y mantén los campos de respaldo como
Private.
Si no se cumple ninguna de esas y solo quieres que los campos viajen juntos con copias
baratas, un Type es más ligero y honesto. No construyas una clase para una bolsa de
tres valores —pero en cuanto esa bolsa necesite hacer algo, una clase es justo lo
correcto.
Cómo ayuda ExcelMaster
Los class module son donde viven los errores de «compila pero se comporta raro»: el zombi
de As New, la edición de referencia compartida que cambia un objeto «solo», el Set
olvidado que lanza el error 91. Cada uno es invisible hasta que muerde, y cada uno viene
de una regla fácil de enunciar y fácil de olvidar con una fecha de entrega encima.
ExcelMaster te
deja describir el objeto que quieres —«un Employee con un nombre, un salario y un método
que devuelva el coste anual, del que pueda tener una lista»— y escribe la clase con Set ... = New explícito, una función de fábrica, campos de respaldo Private expuestos a
través de propiedades y una Collection para guardarlos. Consigues VBA orientado a
objetos idiomático y sin trampas sin tener que acordarte de cada forma en que New y
Set pueden sorprenderte.
Preguntas frecuentes
¿Qué es un class module en VBA?
Un class module es donde defines tu propio tipo de objeto —un plano que agrupa datos
(campos) y comportamiento (métodos y propiedades)—. Una vez
definido, creas instancias independientes de él con New. Es como VBA da soporte a los
objetos propios, un paso más allá de un Type, que guarda solo datos.
¿Cómo creo una instancia de una clase en VBA?
Declara una variable del tipo de la clase y asigna una instancia nueva con Set y New:
Dim e As clsEmployee y luego Set e = New clsEmployee. La palabra clave Set es
obligatoria para los objetos; omitirla (e = New clsEmployee) lanza el error 91. Tras
crearlo, fija sus propiedades: e.Name = "Sarah".
¿Cuál es la diferencia entre Dim As New y Set New en VBA?
Dim e As clsEmployee + Set e = New clsEmployee crea el objeto en esa línea exacta y
mantiene If e Is Nothing con sentido. Dim e As New clsEmployee aplaza la creación
hasta el primer uso, lo que hace que Is Nothing sea siempre False y recrea en
silencio el objeto si lo pones a Nothing y lo vuelves a tocar. Prefiere la forma
explícita Set ... = New.
¿Admite una clase de VBA un constructor con parámetros?
No. El evento Class_Initialize se ejecuta automáticamente cuando se crea una instancia,
pero no admite argumentos, así que no puedes escribir New clsEmployee("Sarah", 65000).
La solución habitual es una función de fábrica en un módulo normal que crea el objeto,
fija sus propiedades y lo devuelve —dándote una forma de una sola línea y con parámetros
de construir el objeto.
¿Cuándo debería usar un class module en lugar de un Type o una Collection?
Usa una clase cuando el registro necesite comportamiento (métodos), cuando quieras muchos objetos independientes que puedas guardar en una Collection, o cuando quieras ocultar campos internos tras propiedades. Si solo necesitas que los campos viajen juntos con copias baratas e independientes, un Type es más ligero y claro.
Probado en
Probado en: Excel 365 (Windows 11), VBA 7.1 — última verificación el 04/08/2026.
Guías relacionadas: VBA Type · VBA Property · VBA Dim · VBA Collection · VBA Dictionary
