jueves, 11 de agosto de 2016

VBA: Los Módulos de Clase en Excel (Class Modules) - parte II.

Al hilo de la entrada anterior (ver) plantearemos hoy un ejemplo de uso concreto de los módulos de clase.

Para el ejemplo implantaremos el cálculo del área y perímetro de un triángulo.

Supongamos tenemos varios elementos/datos de triángulo, de los cuales necesitamos calcular el área y el perímetro:

VBA: Los Módulos de Clase en Excel (Class Modules) - parte II.



La idea será practicar con una clase personalizada (un módulo de clase) que llamaremos: Triangulo_Class:
Siguiendo las indicaciones del post del día anterior, generamos y definimos nuestras variables, las propiedades Get y Let que necesitaremos, y por último generaremos un par de métodos Function.
El código añadido dentro de nuestro módulo de clase es:

'Variables privadas
Private pLado1 As Double
Private pLado2 As Double
Private pLado3 As Double
Private pAltura As Double
''''''''''''''''''''''''''''''''''''''''''''''''''
Public Property Let lado1(valor As Double)
pLado1 = valor
End Property
Public Property Get lado1() As Double
lado1 = pLado1
End Property
'''''''
Public Property Let lado2(valor As Double)
pLado2 = valor
End Property
Public Property Get lado2() As Double
lado2 = pLado2
End Property
''''''''''
Public Property Let lado3(valor As Double)
pLado3 = valor
End Property
Public Property Get lado3() As Double
lado3 = pLado3
End Property
''''''''''
Public Property Let altura(valor As Double)
pAltura = valor
End Property
Public Property Get altura() As Double
altura = pAltura
End Property

'Propiedades de lectura....
Property Get SemiPerimetro() As Double
'calculamos el semiperímetro
SemiPerimetro = (pLado1 + pLado2 + pLado3) / 2
End Property

Property Get Area1() As Double
Area1 = (SemiPerimetro * (SemiPerimetro - pLado1) * (SemiPerimetro - pLado2) * (SemiPerimetro - pLado3)) ^ (1 / 2)
End Property

Property Get Area2() As Double
Area2 = (pLado1 * pAltura) / 2
End Property

Property Get Perimetro() As Double
Perimetro = pLado1 + pLado2 + pLado3
End Property

'métodos---------------------------------------------------------------------------
Function CalculoArea(l_1 As Double, l_2 As Double, l_3 As Double, Optional h As Double) As Double
Dim oTriangulo As Triangulo_Class
Set oTriangulo = New Triangulo_Class
oTriangulo.lado1 = l_1
oTriangulo.lado2 = l_2
oTriangulo.lado3 = l_3
oTriangulo.altura = h

If h <> 0 Then
    'si informamos de la altura
    'calculamos b x h /2
    CalculoArea = oTriangulo.Area2
Else
    'en caso de NO informar altura
    'calculamos con Semiperimetro
    CalculoArea = oTriangulo.Area1
End If

Set oTriangulo = Nothing
End Function
Function CalculoPerimetro(l_1 As Double, l_2 As Double, l_3 As Double) As Double
Dim oTriangulo As Triangulo_Class
Set oTriangulo = New Triangulo_Class
oTriangulo.lado1 = l_1
oTriangulo.lado2 = l_2
oTriangulo.lado3 = l_3

CalculoPerimetro = oTriangulo.Perimetro

Set oTriangulo = Nothing
End Function



Para interactuar en la hoja de cálculo directamente creamos e insertamos otras funciones personalizadas (UDF) en un módulo estándar:

Function CalcArea(l1 As Double, l2 As Double, l3 As Double, Optional h As Double)
Dim oTriangulo As Triangulo_Class
Set oTriangulo = New Triangulo_Class

CalcArea = oTriangulo.CalculoArea(l1, l2, l3, h)

Set oTriangulo = Nothing
End Function
''''''''''''''''''''''''''''''''''''''
Function CalcPerimetro(l1 As Double, l2 As Double, l3 As Double)
Dim oTriangulo As Triangulo_Class
Set oTriangulo = New Triangulo_Class

CalcPerimetro = oTriangulo.CalculoPerimetro(l1, l2, l3)

Set oTriangulo = Nothing
End Function



Son precisamente estas funciones del módulo estándar las que empleamos en las celdas de la hoja de cálculo.

El resumen de lo expuesto es que, tras definir las variables a emplear (tres lados y altura), hemos definido sus propiedades Get y Let para cada una de ellas, que nos permiten recuperar y añadir valor a estas variables.
Además hemos incorporado una serie de propiedades solo de lectura (añadiendo únicamente la propiedad Get):
SemiPerimetro
Area1
Area2
Perimetro

Para finalmente construir unas funciones (métodos) que trabajando sobre las propiedades y variables anteriores, nos permiten recuperar los valores deseados: Área y Perímetro.

Todo esto en un módulo de clase.


El trabajo finaliza al llamar a estos métodos desde otras funciones UDF dentro un módulo estándar:
'CalcArea' y 'CalcPerimetro'.


Como comentábamos en el post del día anterior, por supuesto, es posible hacer lo mismo sin emplear las 'Clases', pero hacerlo simplifica y facilita nuestros procedimientos y macros en Excel.

8 comentarios:

  1. ¡ Excelente Ejemplo !, siempre había dejado de lado los módulos de clase, es bueno aprender otras alternativas y más cuando quien explica lo hace de excelente manera.

    Saludos.

    ResponderEliminar
  2. umm se que soy un aprendiz, pero me gustaria ver este ejemplo del uso de modulos de clase en archivo para poder comprenderlo mejor. si pudieras enviarmelo o compartirlo. Me seria de ayuda :).

    Eh aprendido mucho de este blog. Espero tu ayuda. Graciassssss

    ResponderEliminar
    Respuestas
    1. Hola José Armando,
      lo siento no guardo los ficheros...
      Pero solo sigue las indicaciones y copia y pega el código en los lugares que se indican.
      Saludos y gracias!!

      Eliminar
  3. Hola, quisiera saber si se pueden usar listas de objetos en vba para Excel.
    Por ejemplo una lista de objetos tipo persona, donde sus propiedades sean Edad, nombre, apellido, etc.
    (tal como en VB normal, donde puedo declarar listas con el código "Dim l as new list of Personas".
    Gracias de antemano...

    ResponderEliminar
    Respuestas
    1. Hola,
      puedes definit tu propio 'objeto' con sus propiedades empleando
      Type persona
      Edad as double
      nombre as string
      apellido as string
      ...
      End Type

      Echa un vistazo a http://excelforo.blogspot.com.es/2014/09/vba-como-crear-un-tipo-de-dato-definido.html

      Saludos

      Eliminar
  4. Hola Ismael,
    Estoy empezando a aprender sobre el uso de módulos de clase, me hace falta para una aplicación que quiero implantar y me está generando un quebradero de cabeza.
    Por lo que veo, los valores 11,12 y 13 ya los tienes definidos. Como utilizas las variables l_1, l_2 y l_3, ya se autoasignan, cierto? Después atribuyes el valor l_1 a oTriangulo.lado1 hasta aquí bien.
    Ahora mi rompedero de cabeza.... Defines Property Get lado1 para que cuando utilices en tus funciones plado1 sepa que plado1 es lado1.
    Pero en Property Let lado1 pones pLado1=valor. Qué es "valor"? no lo encuentro en ningún lado escrito, no tiene ningún valor.

    Puedes por favor aclararme esto? Sería de gran ayuda!

    ResponderEliminar
    Respuestas
    1. Hola miclopez3,
      valor está definido como variable Double en:
      Public Property Let lado2(valor As Double)
      pLado2 = valor
      End Property

      será el dato de l_2 (l_1 o l_3 que luego 'cargaremos')
      Saludos

      Eliminar

Nota: solo los miembros de este blog pueden publicar comentarios.