Ejemplo de Modulo de Clase VBA

Antes de empezar, necesitamos dar un poco de contexto a los módulos de clase VBA.

Los módulos de clase son parte esencial de la Programación Orientada a Objetos (POO u OOP por sus siglas en inglés) con VBA en Microsoft Office.

La idea detrás de la POO en VBA consiste en que VBA es un lenguaje de programación basado en objetos. Esto significa que VBA es el lenguaje que se usa para manipular el Modelo de Objetos de Office para aplicaciones, como lo son Excel o bien Word, Access, entre otros.

Para entenderlo mejor, las macros VBA de Excel trabajan comunicándose con el código que Excel tiene implementado en objetos como lo son los libros de trabajo, las hojas de cálculo, los rangos y otros elementos más.

Si queremos trabajar con los módulos de clase VBA que usaremos para crear nuestros propios «objetos», habrá que tener claro a qué nos referimos cuando hablamos de un «objeto» en el contexto de VBA.

La forma más simple de entender la orientación de objetos es por medio de la analogía de delegación en el área de trabajo.

Programación procedural vs dirigida a objetos.

Cuando tenemos que realizar un trabajo, tenemos las opciones de hacerlo nosotros mismos o bien encargar a alguien más que lo haga. Para este ejemplo, digamos que podemos encargar a un miembro de nuestro personal a que escriba un reporte de un tema en particular. Las opciones serían dos:

Hacer el reporte nosotros mismos

En términos de programación, esto es el equivalente a programación procedural no orientada a objetos. Primero habría que hacer nuestra investigación, abrir nuestro procesador de texto y escribir el reporte para luego averiguar las funciones de nuestro procesador y así darle la presentación adecuada.

Hacer que alguien más lo haga (delegarlo)

Y en términos de programación, esto sería el equivalente a orientación de objetos, pues el equivalente sería pedir a alguien «necesito el reporte para hoy a las 4» y tener el reporte a la hora establecida sin haber hecho nada más.

Es así como VBA está diseñado para controlar las aplicaciones de Office por medio del segundo método. Usando un ejemplo con Excel, VBA ve a Excel como un «objeto» o un algo que puede ser manipulado si le envía instrucciones a seguir. Uno como programador no necesita entender cómo es que estas instrucciones son implementadas, o sea que no necesitamos ver el código meramente técnico para realizarlo.

Objetos y Clases en Excel

Siguiendo en el mismo ejemplo, tomemos una hoja de cálculo simple a la cual le queremos escribir la línea de texto «objetos» en la celda B6.

Siendo este un libro de cálculo, queremos que esto se escriba en la primera hoja, pero tenemos dos archivos de Excel abiertos y solo queremos escribir en el segundo.

La instrucción que buscamos dar sería algo como

«Excel, escribe «objetos» en la celda B6 de la primera hoja en el segundo archivo que está abierto».

Yo mero

El código para esto sería el siguiente:

Workbooks(2).Worksheets(1).Range("b6").Value = "objectos"

Pero si hicieramos las cosas un poco más complicadas, podríamos también decir algo como

«Excel, quiero que escribas «objetos» en la celda B6, pero también quiero que el rango del objeto en B6 espere un poco porque puede que necesite hacer otros cambios después».

Yo tambíen

En ese caso, crearíamos un objeto llamado «rngBeeSix» con el siguiente código:

Dim rngBeeSix as Range
set rngBeeSix = Workbooks(2).Worksheets(1).Range("b6")
rngBeeSix.Value = "Objetos"

Dependiendo del alcance de «rngBeeSix», este «esperará» por tanto tiempo como queramos, y esta es la diferencia esencial entre la programación orientada a objetos y la programación procedural.

Aquí hemos creado un «objeto» que en este caso fue la referencia a la celda B6, a la cual le podremos dar instrucciones en cualquier momento. Por ejemplo, podríamos indicar que la fuente en B6 aparezca en negritas por medio del comando:

rngBeeSix.Font.Bold = True

La idea esencial en todo esto es que no estamos presionando teclas manualmente en Excel, sino que estamos usando los objetos de Excel para decirles cuál es el resultado que queremos, siendo el código de implementación el que permanece oculto y no vemos.

Módulos de clase

Así como Excel tiene sus propios objetos incorporados como las hojas de cálculo o los rangos, los cuales están basados en clases incorporadas, nosotros podemos crear nuestros propios objetos usando los módulos de clase. En VBA, un módulo de clase es usado para crear un «Objeto».

La clase tiene la misma relación con el objeto como los planos de un edificio son al edificio mismo, pues describe al edificio pero no lo es, y bien se puede usar para crear replicas del mismo edificio.

Así pues, una clase es usada para crear un objeto, pero entonces ¿Qué es un objeto en código VBA?

Si bien parece una variable, es realmente un mini programa y es ahí donde se encuentra su capacidad.

En un ejemplo real, digamos que queremos modelar las características de varios modelos y marcas de carros en VBA. Empezaríamos por determinar las propiedades generales que tiene un carro:

  • marca,
  • caballos de fuerza,
  • modelo,
  • color,
  • número de puertas,
  • etc;

pero también tiene algunos verbos asociados, como lo son:

  • acelerar,
  • frenar,
  • aplicar el freno de mano,
  • encender el motor,
  • apagar el motor,
  • girar,
  • etc.

El término técnico para estos verbos en la programación orientada a objetos se les llama «métodos«.

Los métodos son funciones o subrutinas en módulos de clase y las Propiedades son variables que contienen descripciones tales como «FORD», «BMW» o «Audi» para la propiedad de «Marca».

Creando una clase para describir un carro básico

Para ello iremos a VBA (lo cual podemos hacer presionando Alt+F11 desde Excel), iremos a la pestaña «Insertar» y elegiremos «Módulo de Clase»:

Modulo de Clase 1

Daremos el nombre «clsCar» a nuestra clase, lo cual haremos dando click a la parte de Nombre en la ventana de propiedades. Nuestra ventana de Visual Basic deberá verse así:

Modulo de Clase 2

Ahora daremos click a nuestra clase en la ventana de proyecto, lo cual cargará nuestro módulo de clase vacío en el editor, en donde ahora tocará añadir el código para darle forma a nuestro módulo.

Espacio de trabajo

A continuación, introduciremos este código en el editor:

Option Explicit

' These are properties
Public Brand As String
Public Model As String
Public FuelType As String
Public EngineSize As String
Public Doors As Integer

' These are methods
ub StartEngine()
' Code for Start Engine Goes Here
MsgBox "Engine Start"
End Sub

Sub StopEngine()
' Code for Stop Engine goes here
MsgBox "Engine Stop"
End Sub

Sub Accelerate()
' Accelerate code here
MsgBox "Speed Up"
End Sub

Sub Brake()
' Brake code here
MsgBox "Braking"
End Sub

Este código es una clase simple de Virtual Basic que representa un carro.

Esto significa que este mismo código puede ser usado para crear cualquier cantidad de «objetos» con la mismas o diferentes características, dándonos así cualquier carro que queramos como resultado.

Propiedades y Metodos

Y suponiendo que ahora tengamos que añadir otro módulo que calcule la responsabilidad fiscal en base a las especificaciones de cada modelo, en donde tenemos una base de datos que contiene los detalles de tu flota de autos de la compañía, o que se trata de una agencia de autos de segunda mano y queremos diferentes métricas en tus tenencias.

En esos casos se podría tener código que le daría vueltas a tu base de datos y para cada objeto llenaría la información en objetos creados desde esta clase, la cual fue escrita una vez y será reusada para cada ocasión en que se haga este ciclo.

Creando un módulo estándar para que ejecute «Objetos»

Ahora bien, para poder hacer uso de esta clase que creamos, vamos a necesitar insertar un módulo ordinario en nuestro proyecto VBA, para lo cual repetiremos el proceso de crear un módulo de clase pero seleccionando la opción modulo.

VBA Modulo normal

Una vez lo hayamos creado y estemos en el editor, vamos a introducir el siguiente código:

Option Explicit

Sub TestCars()
Dim myChrysler As clsCar
Dim myFord As clsCar
Dim SistersRangeRover As clsCar

Set myChrysler = New clsCar
With myChrysler
.Brand = "Chrysler"
.Model = "Voyager"
.FuelType = "Diesel"
.EngineSize = "2.8 Litre"
.Doors = 5
End With

Set SistersRangeRover = New clsCar
With SistersRangeRover
.Brand = "Land Rover"
.Model = "Range Rover"
.EngineSize = "3 Litre"
.FuelType = "Diesel"
.Doors = 5
End With

' These print results to "immediate" window
' (menu View->Immediate Window or "Ctrl+G")
Debug.Print "Fuel Type: " & myChrysler.FuelType
Debug.Print "Brand: " & SistersRangeRover.Brand

myChrysler.StartEngine
myChrysler.Accelerate
SistersRangeRover.StartEngine
SistersRangeRover.Accelerate

End Sub

Aquí notaremos que entre las líneas 4 y 6 hemos definido tres objetos de carro basados en la clase «clsCar» que creamos al inicio.

Dim myChrysler As clsCar
Dim myFord As clsCar
Dim SistersRangeRover As clsCar

En la línea 8 instanciamos el primer objeto de carro «myChrysler», lo que significa que un objeto myChrysler es creado en memoria de computadora basado en «clsCar».

Set myChrysler = New clsCar

Entre las líneas 9 y 15 se han llenado los detalles del objeto myChrysler.

With myChrysler
.Brand = "Chrysler"
.Model = "Voyager"
.FuelType = "Diesel"
.EngineSize = "2.8 Litre"
.Doors = 5
End With

De manera similar, entre las líneas 14 y 23 se han llenamo los detalles del objeto «SistersRangeRover».

Set SistersRangeRover = New clsCar
With SistersRangeRover
.Brand = "Land Rover"
.Model = "Range Rover"
.EngineSize = "3 Litre"
.FuelType = "Diesel"
.Doors = 5
End With

El punto de esto es que cada detalle se va llenando con el código trabaja a través de «clsCar» y pone los resultados en una parte diferente de la memoria de computadora, por lo cual varios objetos pueden ser creados de la misma clase de código.

Ahora vamos a correr este código en modo Debug.

Para ello pasaremos nuestro cursor en cualquier punto dentro de la rutina «TestCars» (no importa dónde exactamente) y presionaremos F8 o bien en la pestaña «Debug» en VBA y luego en «Entrar en». Continuaremos presionando F8 hasta que alcancemos la línea 30.

Depurador de codigo

Los resultados de las líneas 27 y 28 en el código de arriba, las declaraciones del debug.print pueden verse a la derecha en la ventana inmediata, como lo son el tipo de combustible y la marca del auto.

Debug.Print "Fuel Type: " & myChrysler.FuelType
Debug.Print "Brand: " & SistersRangeRover.Brand

Lo que aparezca señalado en amarillo indicará que el debugger se detuvo en esa línea y está pendiente a ejecutarlo.

Depurador de codigo 2

Las líneas de la 30 a la 33 nos muestran «métodos» de ejecución de los dos objetos, los cuales son funciones o subrutinas, lo cual los hace mini programas por sí mismos.

Examinando objetos en la memoria

Podemos examinar los objetos en la memoria si le damos un vistazo a la ventana «Locales» en Visual Basic.

Ventanas locales

Esta ventana nos será bastante útil, pues nos permitirá ver los contenidos de todas las variables que tengamos en nuestro alcance actual. Aquí podemos ver que la memoria de variables creada por «myChrysler» y «SistersRangeRover» tienen valores para todas las propiedades que fueron llenadas.

Ventana local

También podemos ver que una variable de memoria fue creada para «myFord», aunque dado que esta no fue instanciada con la línea.

Set SistersRangeRover = New clsCar

Es por lo tanto una variable de memoria vacía, pues está establecida como «Nothing».

Paso para los «Métodos» finales

Las últimas cuatro líneas del código entre las líneas 30 y 33 del módulo «mMain» nos muestran llamando varios «métodos» o bien verbos de los objetos, como establecimos anteriormente, siendo estos «iniciar motor», «acelerar», «frenar» y «apagar motor».

myChrysler.StartEngine
myChrysler.Accelerate
SistersRangeRover.StartEngine
SistersRangeRover.Accelerate

Lo interesante sobre esto es que si continuamos con el debug del código presionando la tecla F8, veremos que sin importar si estamos sobre myChrysler o SisterRangeRover, el mismo módulo de código clsCar es ejectutado. Este valor es verdadero para todo el código en mMain que llame en clsCar.

Los «objetos» nos permiten manejar complejidad, ya que si imaginamos problemas reales como objetos, entonces podemos fragmentar el problema en pedazos pequeños (en este caso pedazos de código y módulos de clase) y comunicar cada pedazo con el otro y solo debe ser escrito una vez.

Por ejemplo, un sistema de control de tráfico aéreo podría tener una clase llamada «Avión» con propiedades tales como:

  • la velocidad,
  • la altura,
  • su destino y
  • métodos como ascender o descender.

Todo esto podría interactuar con otra clase cuyo trabajo sea manejar todos estos objetos y asegurarse de que ninguno se acerque a cierta distancia del otro; lo cual, en opinión de algunos, solo puede ser logrado mediando la programación orientada a objetos.

Con este ejemplo de Modulo Clase VBA puedes darte una idea de la versatilidad de los nuevos códigos de Excel y su utilidad. Cualquier duda nos leemos abajo.

Ejemplo de Modulo de Clase VBA
Scroll hacia arriba