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

VBA Type en Excel — agrupa campos relacionados en una sola variable (tipos definidos por el usuario frente a una clase)

|

VBA Type en Excel — agrupa campos relacionados en una sola variable (tipos definidos por el usuario frente a una clase)

TL;DR — Un Type (un tipo definido por el usuario, o UDT) te deja nombrar una forma una sola vez y llevar todos sus campos en una única variable. En lugar de hacer malabares con tres arrays que deben mantenerse alineados por índice, tienes un solo array de registros. Un Type es un tipo de valor: asignar b = a copia todos los campos, así que las dos variables son independientes —lo contrario de una instancia de clase, que se comparte—. Decláralo en la parte superior de un módulo estándar y recurre a un class module solo cuando el registro necesite hacer algo.

' En la parte superior de un módulo estándar, antes de cualquier Sub o Function:
Type Employee
    Name   As String
    Age    As Long
    Salary As Currency
End Type

Sub Demo()
    Dim e As Employee          ' una variable contiene los tres campos
    e.Name = "Sarah"
    e.Age = 34
    e.Salary = 65000

    Dim copy As Employee
    copy = e                   ' COPIA POR VALOR — cada campo duplicado
    copy.Salary = 99000        ' cambiar la copia NO toca a e
    MsgBox e.Salary            ' sigue siendo 65000
End Sub

La mayoría del código VBA que «lleva la cuenta de varias cosas sobre un mismo elemento» acaba como arrays paralelos —names(), ages(), salaries()— que tienen que mantenerse todos en el mismo orden. Ordena uno y olvídate de los demás, y el nombre de la fila 5 pasa a pertenecer al salario de la fila 12, sin ningún error que te avise. Un Type lo arregla de raíz: los campos ya no pueden separarse a la deriva, porque viven en una sola variable.

Lo que aprenderás

  • El modelo mental — una fila como una sola variable
  • Dónde hay que declarar un Type (y por qué dentro de un Sub falla)
  • La regla que sorprende a todo el mundo — un Type copia, no comparte
  • La verdadera recompensa — un solo array de registros en lugar de arrays paralelos
  • El límite duro — un Type no puede contener comportamiento ni ir en una Collection
  • Type frente a class module — cómo elegir

El modelo mental: una fila como una sola variable

Piensa en un Type como una fila de una tabla, ascendida a variable. La fila de una hoja para un empleado tiene un nombre, una edad y un salario uno al lado del otro; un Type te da esa misma agrupación en el código. Defines las columnas una vez (Type Employee ... End Type) y cada Dim e As Employee es una fila nueva con esas mismas casillas.

Esa es toda la idea: deja de pasar valores sueltos que van juntos y pasa una sola cosa con etiqueta en su lugar. Una función que necesita un empleado recibe un único argumento Employee, no tres parámetros que tienes que mantener en el orden correcto.

Dónde hay que declarar un Type

Una declaración Type vive a nivel de módulo —en la parte más alta de un módulo estándar, por encima de cualquier procedimiento. Métela dentro de un Sub y el proyecto no compilará. Ahí tropieza quien trata a Type como a Dim: Dim es una instrucción que ejecutas dentro de un procedimiento, pero Type es una declaración que define una forma para todo el módulo o proyecto.

Dos reglas de colocación que merece la pena memorizar:

  • Public Type (lo predeterminado a nivel de módulo) hace que el tipo se pueda usar en todo el proyecto. Usa Private Type para dejarlo acotado a un módulo.
  • No puedes declarar un Public Type dentro de un class module — VBA lo rechaza con «No se puede definir un tipo público definido por el usuario dentro de un módulo de objeto privado». Guarda tus Type compartidos en un módulo normal (Module1, o un módulo Types dedicado), no en una clase ni en el código de una hoja.

La regla que sorprende a todo el mundo: un Type copia, no comparte

Esto es lo más importante que hay que entender sobre un Type, porque es el punto exacto en el que se diferencia de un objeto. Un Type es un tipo de valor. Cuando escribes copy = e, VBA duplica todos los campos en una variable nueva e independiente:

Dim a As Employee, b As Employee
a.Salary = 50000
b = a                 ' copia completa de todos los campos
b.Salary = 70000      ' edita solo b
Debug.Print a.Salary  ' 50000  — a queda intacta

Compáralo con una instancia de clase, donde Set b = a hace de a y b dos nombres para el mismo objeto, así que editar uno edita ambos. Si alguna vez te ha pillado un objeto que cambia «solo» después de asignarlo en algún sitio, el comportamiento de copia-al-asignar del Type es el antídoto —y a menudo justo lo que quieres—.

El único lugar donde la copia no ocurre es al pasarlo a un procedimiento. Un argumento Type es ByRef por defecto, así que un Sub puede cambiar tu original:

Sub GiveRaise(emp As Employee)      ' ByRef por defecto
    emp.Salary = emp.Salary * 1.1   ' muta el registro del llamador
End Sub

Pásalo ByVal si quieres que el procedimiento llamado trabaje sobre una copia privada —la misma regla de ByRef frente a ByVal que gobierna las variables corrientes.

La verdadera recompensa: un solo array de registros

Aquí es donde un Type se gana su sitio. En lugar de N arrays paralelos que tienes que mantener alineados a mano, declaras un solo array de registros:

Dim staff(1 To 100) As Employee
staff(1).Name = "Sarah"
staff(1).Salary = 65000
staff(2).Name = "Tom"
staff(2).Salary = 58000

' Ordena, filtra o reordena staff() y cada campo se mueve junto —
' un nombre nunca podrá desincronizarse de su salario otra vez.

El modo de fallo que esto elimina es silencioso y desagradable: con names(), ages() y salaries() como arrays separados, cualquier operación que reordene uno —un ordenamiento, una inserción, un borrado— desincronizará a los demás salvo que te acuerdes de aplicarla a todos de forma idéntica. Con un array de Employee no hay nada que mantener sincronizado, porque los campos nunca se separaron unos de otros.

El límite duro: sin comportamiento y sin Collection

Un Type es deliberadamente tonto —guarda datos y nada más—. Eso le da dos límites duros que te dicen cuándo se te ha quedado pequeño:

  • No puede tener métodos. En cuanto tu registro necesita hacer algo —validar su propia edad, darse formato como cadena, recalcular un total—, un Type no puede ayudar. El comportamiento le corresponde a un class module.
  • No puede ir en una Collection ni en un Dictionary. Esos almacenes guardan valores Variant, y un UDT no se puede convertir a Variant. Prueba coll.Add e con un Type y VBA se niega. Si necesitas un almacén de registros que crezca y con clave, eso solo ya es motivo para pasarte a una clase, cuyas instancias sí son objetos que una Collection acepta.

Type frente a class module: cómo elegir

Type (UDT) Class module
Contiene Solo datos Datos y comportamiento
Categoría Tipo de valor Tipo de referencia (objeto)
b = a Copia todos los campos Set b = a comparte una instancia
Se declara en Módulo estándar, por encima de los procedimientos Su propio class module
¿Guardar en una Collection? No
Se crea con Dim e As Employee Set e = New clsEmployee
Mejor cuando Los campos solo necesitan viajar juntos El registro necesita métodos o debe vivir en una colección

Mi regla general: si los campos solo necesitan mantenerse juntos y quieres copias baratas e independientes, un Type es la herramienta correcta —tirar de una clase aquí es sobreingeniería—. Pásate a una clase en cuanto el registro necesite comportamiento, o en cuanto necesites tener muchos de ellos en una Collection. Todo lo que queda en medio es cuestión de criterio, y «empieza con el Type y promuévelo luego» es un valor por defecto perfectamente válido.

Cómo ayuda ExcelMaster

Decidir entre arrays paralelos, un Type y una clase completa —y luego acordarte de que un Type copia mientras que un objeto comparte— es justo la clase de decisión de modelado que es fácil equivocar de forma sutil. Los errores que provoca (un array desincronizado, un objeto que muta «solo») compilan sin problemas y solo asoman más tarde.

ExcelMaster te deja describir los datos en su lugar. Di «necesito llevar el nombre, la edad y el salario de una lista de empleados y ordenarlos por salario» y modelará los registros por ti —un array de un Type, con el ordenamiento aplicado para que nada se desincronice— y te explicará, en el código, cuándo habría elegido una clase en su lugar. Consigues la estructura correcta sin tener que retener en la cabeza todas las reglas de valor frente a referencia.

Preguntas frecuentes

¿Qué es un Type en VBA?

Un Type (tipo definido por el usuario, o UDT) es una estructura de datos propia que agrupa varios campos relacionados bajo un mismo nombre —por ejemplo un Employee con Name, Age y Salary—. Lo declaras una vez con Type ... End Type en la parte superior de un módulo estándar y luego lo usas como cualquier otro tipo: Dim e As Employee. Deja que los valores relacionados viajen juntos como una sola variable en lugar de como variables separadas y fáciles de desincronizar.

¿Cuál es la diferencia entre un Type y un class module en VBA?

Un Type guarda solo datos y es un tipo de valor —asignar uno a otro copia todos los campos, así que ambos son independientes—. Un class module guarda datos y comportamiento (métodos) y es un tipo de referenciaSet b = a hace que ambos nombres apunten a la misma instancia—. Usa un Type para un registro pasivo; usa una clase cuando el registro necesite métodos o deba guardarse en una Collection.

¿Dónde declaro un Type en VBA?

A nivel de módulo, por encima de cualquier procedimiento, en un módulo estándar. Declarar un Type dentro de un Sub o Function es un error de compilación. Usa Public Type (lo predeterminado) para compartirlo en todo el proyecto, o Private Type para limitarlo a un módulo. No puedes declarar un Public Type dentro de un class module.

¿Puedo guardar un Type de VBA en una Collection o un Dictionary?

No. Una Collection y un Dictionary guardan valores Variant, y un tipo definido por el usuario no se puede convertir a Variant, así que coll.Add someType falla. Si necesitas un almacén de registros que crezca o con clave, usa un class module en su lugar —sus instancias son objetos que una Collection acepta— o guarda los registros en un array del Type.

¿Asignar una variable Type a otra copia o comparte los datos?

Copia. Como un Type es un tipo de valor, b = a duplica todos los campos en una variable independiente; cambiar b después no afecta a a. Esto es lo contrario de los objetos (instancias de clase), donde Set b = a comparte una sola instancia. La única excepción es pasar un Type a un procedimiento, que es ByRef por defecto y por tanto puede mutar el registro del llamador.

Probado en

Probado en: Excel 365 (Windows 11), VBA 7.1 — última verificación el 04/08/2026.

Guías relacionadas: VBA Class Module · VBA Property · VBA Data Types · VBA Array · VBA ByRef frente a ByVal