Pregunta

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

Estoy suponiendo que el el desarrollo acelerado y la reducción de introducir errores es un beneficio común para la mayoría de los lenguajes que soportan la programación orientada a objetos.Pero con VBA, hay un criterio específico?

¿Fue útil?

Solución

Depende de a quién se va a desarrollar y mantener el código.Típico de "Usuario avanzado" macro escritores de hacking pequeña ad-hoc aplicaciones pueden ser confundidos por el uso de clases.Pero para cosas más serias de desarrollo, las razones para usar las clases son las mismas que en otros idiomas.Tiene las mismas restricciones que en VB6 - la herencia -, pero usted puede tener polimorfismo mediante el uso de interfaces.

Un buen uso de las clases es para representar entidades, y las colecciones de las entidades.Por ejemplo, a menudo veo que el código de VBA que copia un rango de Excel en una matriz de dos dimensiones, manipula entonces 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 legible para copiar el rango en una colección de objetos con el nombre apropiado propiedades, algo como:

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

Otro ejemplo es el uso de clases para implementar el RAII patrón de diseño (google).Por ejemplo, una cosa que necesita hacer es desproteger una hoja de cálculo, hacer algunas manipulaciones, a continuación, proteger de nuevo.El uso de una clase se asegura de que la hoja de cálculo 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

Usted puede utilizar esto para simplificar el 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 este Sub salidas, objWorksheetProtector sale del ámbito, y la hoja de cálculo está protegida de nuevo.

Otros consejos

Creo que el criterio es el mismo que en otros idiomas

Si usted necesita para unir varias piezas de datos y de algunos de los métodos y también se ocupan específicamente de lo que sucede cuando el objeto es creado/terminado, las clases son ideales

dicen que si usted tiene algunos de los procedimientos que se desencadena cuando se abre un formulario y uno de ellos es tomar un largo tiempo, usted podría decidir que usted desea tomar el tiempo de cada etapa......

Usted podría crear un cronómetro de la clase con los métodos para las funciones obvias de arranque y parada, luego, puede agregar una función para recuperar el tiempo y el informe en un archivo de texto, usando un argumento que representa el nombre del proceso de ser programado.Usted podría escribir la lógica para registrar sólo el más lento actuaciones de investigación.

Luego, puede agregar una barra de progreso objeto con métodos para abrir y cerrar y mostrar los nombres de la acción actual, junto con los tiempos de ms y es probable que el resto de las anteriores almacenados informes, etc

Otro ejemplo podría ser si no te gusta el Acceso del grupo de usuarios de basura, usted puede crear su propia clase de Usuario con métodos de claves de acceso y salida y las características a nivel de grupo de control de acceso de usuario/auditoría/registro de ciertas acciones de seguimiento de errores, etc

Por supuesto, usted puede hacer esto mediante un conjunto de la relación de los métodos y de un montón de variables que pasa, pero para tener todo encapsulado en una clase sólo parece mejor para mí.

Que haces tarde o temprano se acercan a los límites de VBA, pero es un lenguaje potente y si tu empresa te ata a ella en realidad se puede obtener algunas buenas, soluciones complejas fuera de él.

Las clases son muy útiles cuando se trabaja con la más compleja de las funciones de la API, y en particular cuando se requiere una estructura de datos.

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

Me gusta envolver la estructura (UDT) y la función de la API de declaraciones en una clase CfileDialog.El evento Class_Initialize establece los valores por defecto de la estructura de los miembros, de modo que cuando yo uso la clase, sólo necesito conjunto de los miembros quiero cambiar (a través de los procedimientos de Propiedad).Bandera constantes se implementa como una Enumeración.Así, por ejemplo, para seleccionar 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 define el defecto en el directorio Mis Documentos, aunque si yo quería podía cambiar con el InitDir de la propiedad.

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

Yo no diría que hay un criterio específico, pero yo nunca he encontrado un lugar útil para las Clases de uso en el código de VBA.En mi mente está tan ligado a los modelos existentes en torno a las aplicaciones de Office que la adición de abstracción adicional fuera de ese modelo de objeto sólo confunde las cosas.

Eso no quiere decir que uno no podía encontrar un lugar útil para una clase en VBA, o hacer perfectamente útil cosas utilizando una clase, sólo que nunca he encontrado útiles en ese entorno.

También se puede reutilizar el código de VBA sin el uso de clases reales.Por ejemplo, si usted tiene un llamado, VBACode.Usted puede tener acceso a cualquier función o sub en cualquier módulo con la siguiente sintaxis:

VBCode.mysub(param1, param2)

Si se crea una referencia a una plantilla/doc (como si fuera una dll), puede hacer referencia por el código de otros proyectos de la misma manera.

El desarrollo de software, incluso con Microsoft Access, utilizando Programación Orientada a Objetos en general es una buena práctica.Va a permitir la escalabilidad en el futuro, permitiendo a los objetos ser débilmente acoplados, junto con un número de ventajas.Básicamente, esto significa que los objetos en el sistema será menos dependiente de los demás, por lo que la refactorización se convierte en mucho más fácil.Usted puede lograr esto es el Acceso mediante Módulos de Clase.La desventaja es que usted no puede realizar la Clase de Herencia o Polimorfismo en VBA.En el final, no hay ninguna regla dura y rápida sobre el uso de clases, sólo las mejores prácticas.Pero hay que tener en cuenta que a medida que crece la aplicación, más fácil es mantener el uso de clases.

Para los datos de recursión (un.k.una.Lista de materiales manejo), una clase personalizada es sumamente útil y creo que a veces indispensable.Usted puede hacer una función recursiva, sin un módulo de clase, pero una gran cantidad de problemas con los datos no pueden tratarse de manera eficaz.

(No sé por qué las personas no están vendiendo la lista de materiales de la biblioteca-juegos para VBA.Tal vez el XML herramientas han hecho una diferencia.)

Múltiples instancias de formulario es el común de la aplicación de una clase (muchos de los problemas de la automatización de lo contrario son irresolubles), supongo que la pregunta es acerca de personalizado clases.

Yo las clases de uso cuando tengo que hacer algo y una clase va a hacer mejor:) Por ejemplo, si usted necesita para responder a (o intersección) eventos, entonces usted necesita una clase.Algunas personas odian a tipos definidos por el usuario (definido por el usuario tipos) pero me gustan, así que yo los uso si quiero llanura inglés de auto-documentación de código.La farmacia.NCPDP ser mucho más fácil de leer, a continuación, strPhrmNum :) Pero un UDT es limitado, por lo que decir quiero ser capaz de establecer la Farmacia.NCPDP y de todas las otras propiedades de rellenar.Y también quiero hacer lo que no se puede accidentalmente alterar los datos.Entonces necesito una clase, porque no tiene propiedades readonly en una UDT, etc.

Otra consideración es el de la simple lectura.Si usted está haciendo las estructuras de datos complejas, que a menudo es beneficioso saber que sólo necesitan llamar a la Compañía.Propietario.Teléfono.Código de área, a continuación, tratando de seguir la pista de donde todo está estructurado.Especialmente para las personas que tienen que mantener esa base de 2 años después de la izquierda:)

Mis dos centavos es "Código Con Propósito".No utilice una clase sin una razón.Pero si usted tiene una razón y luego hacerlo:)

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

Se puede definir un sql clase de contenedor en el acceso que es más conveniente que los conjuntos de registros y definiciones de consulta.Por ejemplo, si desea actualizar una tabla basándose en un criterio en otra tabla relacionada, usted puede utilizar combinaciones.Usted podría construido una vba recorset y definición de consulta para hacer que sin embargo me resulta más fácil con una clase.Además, su aplicación puede tener algún concepto que necesitan más que 2 tablas, podría ser el mejor de la omi para las clases de uso para eso.E. g.La aplicación realizar un seguimiento de incidentes.Incidente tiene varios atributos que se llevará a cabo en varias mesas {los usuarios y sus contactos o perfiles, descripción del incidente;seguimiento del estado;Listas de verificación para ayudar a que el oficial de apoyo a la respuesta tonthe incidente;Respuesta ...} .Para mantener un seguimiento de todas las consultas y relaciones involucradas, la programación orientada a objetos que pueden ser útiles.Es un alivio para ser capaz de hacer Incidente.Actualización(xxx) en lugar de todo el código ...

No veo por qué los criterios de VBA iba a ser diferente de otro idioma, especialmente si usted se refiere a VB.NET.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top