Aquí podría ser tu PUBLICIDAD


¿Cuándo usar una clase en VBA?

votos
36

¿Cuándo es apropiado usar una clase en Visual Basic para Aplicaciones (VBA)?

Asumo que el desarrollo acelerado y la reducción de la introducción de errores es un beneficio común para la mayoría de los lenguajes que admiten OOP. Pero con VBA, ¿hay un criterio específico?

Publicado el 23/09/2008 a las 03:59
fuente por usuario Curtis Inderwiesche
En otros idiomas...        العربية       

11 respuestas

votos
49

Depende de quién va a desarrollar y mantener el código. Los macro escritores típicos de "Power User" que piratean pequeñas aplicaciones ad-hoc pueden confundirse al usar las clases. Pero para un desarrollo serio, las razones para usar clases son las mismas que en otros idiomas. Tiene las mismas restricciones que VB6, sin herencia, pero puede tener polimorfismo mediante el uso de interfaces.

Un buen uso de las clases es representar entidades y colecciones de entidades. Por ejemplo, a menudo veo código VBA que copia un rango de Excel en una matriz bidimensional, luego manipula la matriz bidimensional con un código como:

Total = 0
For i = 0 To NumRows-1
    Total = Total + (OrderArray(i,1) * OrderArray(i,3))
Next i

Es más fácil copiar el rango en una colección de objetos con propiedades apropiadamente nombradas, algo como:

Total = 0
For Each objOrder in colOrders
    Total = Total + objOrder.Quantity * objOrder.Price
Next i

Otro ejemplo es utilizar clases para implementar el patrón de diseño RAII (google for it). Por ejemplo, una cosa que debo hacer es desproteger una hoja de cálculo, hacer algunas manipulaciones y luego protegerla de nuevo. El uso de una clase garantiza que la hoja de trabajo siempre estará protegida de nuevo, incluso si se produce un error en su código:

--- WorksheetProtector class module ---

Private m_objWorksheet As Worksheet
Private m_sPassword As String

Public Sub Unprotect(Worksheet As Worksheet, Password As String)
    ' Nothing to do if we didn't define a password for the worksheet
    If Len(Password) = 0 Then Exit Sub

    ' If the worksheet is already unprotected, nothing to do
    If Not Worksheet.ProtectContents Then Exit Sub

    ' Unprotect the worksheet
    Worksheet.Unprotect Password

    ' Remember the worksheet and password so we can protect again
    Set m_objWorksheet = Worksheet
    m_sPassword = Password
End Sub

Public Sub Protect()
    ' Protects the worksheet with the same password used to unprotect it
    If m_objWorksheet Is Nothing Then Exit Sub
    If Len(m_sPassword) = 0 Then Exit Sub

    ' If the worksheet is already protected, nothing to do
    If m_objWorksheet.ProtectContents Then Exit Sub

    m_objWorksheet.Protect m_sPassword
    Set m_objWorksheet = Nothing
    m_sPassword = ""
End Sub

Private Sub Class_Terminate()
    ' Reprotect the worksheet when this object goes out of scope
    On Error Resume Next
    Protect
End Sub

A continuación, puede usar esto para simplificar su código:

Public Sub DoSomething()
   Dim objWorksheetProtector as WorksheetProtector
   Set objWorksheetProtector = New WorksheetProtector
   objWorksheetProtector.Unprotect myWorksheet, myPassword

   ... manipulate myWorksheet - may raise an error

End Sub 

Cuando sale esta Sub, objWorksheetProtector sale del alcance y la hoja de trabajo se protege de nuevo.

Respondida el 27/09/2008 a las 11:51
fuente por usuario Joe


Aquí podría ser tu PUBLICIDAD


votos
8

Creo que el criterio es el mismo que en otros idiomas

Si necesita unir varias piezas de datos y algunos métodos y también manejar específicamente lo que sucede cuando se crea / finaliza el objeto, las clases son ideales

Digamos que si tiene unos pocos procedimientos que se activan cuando abre un formulario y uno de ellos tarda mucho tiempo, puede decidir que desea medir cada etapa ...

Podría crear una clase de cronómetro con métodos para las funciones obvias para iniciar y detener, luego podría agregar una función para recuperar el tiempo hasta el momento e informarlo en un archivo de texto, usando un argumento que represente el nombre del proceso que se está programando. Podría escribir lógica para registrar solo las actuaciones más lentas para la investigación.

A continuación, puede agregar un objeto de la barra de progreso con métodos para abrirlo y cerrarlo y mostrar los nombres de la acción actual, junto con los tiempos en ms y el tiempo probable restante en función de informes almacenados anteriores, etc.

Otro ejemplo podría ser que si no te gusta la basura del grupo de usuarios de Access, puedes crear tu propia clase de usuario con métodos para ingresar y salir y funciones para control de grupo de usuarios / control / auditoría / registrar ciertas acciones / errores de seguimiento, etc.

Por supuesto, podrías hacer esto usando un conjunto de métodos no relacionados y muchos pases variables, pero tener todo encapsulado en una clase me parece mejor.

Tarde o temprano te acercarás a los límites de VBA, pero es un lenguaje bastante poderoso y si tu empresa te ata con eso puedes obtener algunas soluciones buenas y complejas.

Respondida el 25/09/2008 a las 12:17
fuente por usuario ajp

votos
5

Las clases son extremadamente útiles cuando se trata de las funciones de API más complejos, y en particular cuando se requieren una estructura de datos.

Por ejemplo, el GetOpenFileName () y GetSaveFileName () funciones toman un stucture OPENFILENAME con muchos miembros. es posible que no necesita tomar ventaja de todos ellos, pero están ahí y debe ser inicializado.

Me gusta para envolver la estructura (UDT) y las declaraciones de funciones API en una clase de CFileDialog. El evento Class_Initialize establece los valores por defecto de los miembros de la estructura, de manera que cuando se utiliza la clase, lo único que necesito fijar los miembros que desea cambiar (a través de procedimientos de propiedad). constantes de la bandera se implementan como una enumeración. Así, por ejemplo, elegir una hoja de cálculo para abrir, mi código podría tener este aspecto:

Dim strFileName As String
Dim dlgXLS As New CFileDialog

With dlgXLS
  .Title = "Choose a Spreadsheet"
  .Filter = "Excel (*.xls)|*.xls|All Files (*.*)|*.*"
  .Flags = ofnFileMustExist OR ofnExplorer

  If OpenFileDialog() Then
    strFileName = .FileName
  End If
End With
Set dlgXLS = Nothing

La clase establece el directorio predeterminado en Mis documentos, aunque si quería que podría cambiar con la propiedad InitDir.

Este es sólo un ejemplo de cómo una clase puede ser muy beneficioso en una aplicación de VBA.

Respondida el 13/02/2012 a las 06:26
fuente por usuario Mike

votos
5

No diría que hay un criterio específico, pero nunca he encontrado un lugar útil para usar Classes en el código VBA. En mi opinión, está tan vinculado a los modelos existentes alrededor de las aplicaciones de Office que agregar abstracción adicional fuera de ese modelo de objetos solo confunde las cosas.

Eso no quiere decir que no se pueda encontrar un lugar útil para una clase en VBA, o hacer cosas perfectamente útiles usando una clase, solo que nunca los he encontrado útiles en ese entorno.

Respondida el 23/09/2008 a las 04:40
fuente por usuario cori

votos
3

También puede reutilizar el código VBA sin usar clases reales. Por ejemplo, si tiene una llamada, VBACode. Puede acceder a cualquier función o sub en cualquier módulo con la siguiente sintaxis:

VBCode.mysub(param1, param2)

Si crea una referencia a una plantilla / documento (como lo haría con una dll), puede hacer referencia al código de otros proyectos de la misma manera.

Respondida el 24/09/2008 a las 12:03
fuente por usuario JonnyGold

votos
2

Yo uso las clases si quiero crear un paquete de auto-encapsulado de código que voy a utilizar a través de muchos proyectos de VBA que vienen a través de varios clientes.

Respondida el 13/02/2012 a las 02:29
fuente por usuario Jason TEPOORTEN

votos
2

Utilizo clases cuando necesito hacer algo y una clase lo hace mejor :) Por ejemplo, si necesita responder a eventos (o interceptarlos), entonces necesita una clase. Algunas personas odian los UDT (tipos definidos por el usuario) pero me gustan, así que los uso si quiero un código de auto-documentación en inglés. Pharmacy.NCPDP es mucho más fácil de leer que strPhrmNum :) Pero un UDT es limitado, así que supongamos que quiero establecer Pharmacy.NCPDP y que todas las demás propiedades se completen. Y también quiero hacerlo para que no puedas alterar accidentalmente los datos. Entonces necesito una clase, porque no tienes propiedades de solo lectura en un UDT, etc.

Otra consideración es simplemente legibilidad simple. Si está haciendo estructuras de datos complejas, a menudo es beneficioso saber que solo necesita llamar a Company.Owner.Phone.AreaCode y luego intentar realizar un seguimiento de dónde está estructurado todo. Especialmente para las personas que tienen que mantener esa base de código 2 años después de que te fuiste :)

Mis propios dos centavos son "Código con Propósito". No uses una clase sin una razón. Pero si tienes una razón, hazlo :)

Respondida el 12/06/2009 a las 10:16
fuente por usuario Oorang

votos
2

Para la recursión de datos (también conocido como manejo de BOM), una clase personalizada es críticamente útil y creo que a veces es indispensable. Puede realizar una función recursiva sin un módulo de clase, pero muchos problemas de datos no se pueden abordar de manera efectiva.

(No sé por qué las personas no venden sus colecciones de BOM para VBA. Tal vez las herramientas XML hayan marcado la diferencia).

Las instancias de formularios múltiples son la aplicación común de una clase (muchos problemas de automatización no tienen solución), supongo que la pregunta es sobre clases personalizadas .

Respondida el 12/06/2009 a las 05:51
fuente por usuario Smandoli

votos
2

El desarrollo de software, incluso con Microsoft Access, utilizando Programación Orientada a Objetos es generalmente una buena práctica. Permitirá escalabilidad en el futuro al permitir que los objetos se acoplen libremente, junto con una serie de ventajas. Esto básicamente significa que los objetos en su sistema serán menos dependientes entre sí, por lo que la refacturación se vuelve mucho más fácil. Puede lograr esto es Acceso utilizando módulos de clase. El inconveniente es que no puede realizar herencia de clase o polimorfismo en VBA. Al final, no hay una regla rígida sobre el uso de clases, solo mejores prácticas. Pero tenga en cuenta que a medida que su aplicación crece, es más fácil mantener el uso de clases.

Respondida el 25/09/2008 a las 06:28
fuente por usuario jinsungy

votos
0

Se puede definir una clase contenedora sql en el acceso que es más conveniente que los conjuntos de registros y definiciones de consulta. Por ejemplo, si desea actualizar una tabla basada en un criterio en otra tabla relacionada, no se puede usar combinaciones. Se podría construir una recorset VBA y definición de consulta para hacer eso, sin embargo me resulta más fácil con una clase. Además, su aplicación puede tener algún concepto que necesita más que 2 mesas, tal vez sería mejor imo usar clases para eso. Por ejemplo You incidentes pista aplicación. Incidente tiene varios atributos que llevará a cabo en varias tablas {usuarios y sus contactos o perfiles, descripción del incidente; seguimiento del estado; Las listas de verificación para ayudar al oficial de apoyo para responder tonthe incidente; Responder ...}. Para realizar un seguimiento de todas las consultas y relaciones involucradas, oop puede ser útil. Es un alivio poder hacer Incident.Update (xxx) en lugar de toda la codificación ...

Respondida el 03/08/2017 a las 03:37
fuente por usuario Bellow Akambi

votos
-1

No veo por qué el criterio para VBA sería diferente de otro idioma, particularmente si se refiere a VB.NET.

Respondida el 23/09/2008 a las 04:01
fuente por usuario JosephStyons


Aquí podría ser tu PUBLICIDAD