🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA Class Module en Excel — construye tu propio objeto (plano frente a instancia, y la trampa de As New)

|

VBA Class Module en Excel — construye tu propio objeto (plano frente a instancia, y la trampa de As New)

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 clave Class dentro) y los objetos son tipos de referencia, así que Set b = a hace de a y b dos nombres para la misma instancia. Prefiere el explícito Set x = New clsThing frente a Dim 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 ... = New y la trampa de As New
  • La regla que sorprende a todo el mundo — los objetos comparten, no copian
  • Preparación y limpieza — Class_Initialize y el constructor que falta
  • Cuándo una clase gana a un Type o a una Collection

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. Con As New, en cuanto tocas e para comprobarlo, VBA lo instancia —así que Is Nothing es, en la práctica, siempre False—. Pierdes la capacidad de preguntar «¿se llegó a crear esto alguna vez?».
  • Se resucita a sí mismo. Pon una variable As New a Nothing, 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 Sub auxiliares.
  • 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