oop - que - ¿Cuándo usar una clase en VBA?
lista de objetos vba excel (11)
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.
¿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?
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.
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.
Las clases son extremadamente útiles cuando se trata de las funciones API más complejas, y particularmente cuando requieren una estructura de datos.
Por ejemplo, las funciones GetOpenFileName () y GetSaveFileName () toman una estructura OPENFILENAME con muchos miembros. es posible que no necesite aprovechar todas ellas, pero están ahí y deben inicializarse.
Me gusta ajustar la estructura (UDT) y las declaraciones de funciones de API en una clase CfileDialog. El evento Class_Initialize establece los valores predeterminados de los miembros de la estructura, de modo que cuando uso la clase, solo necesito establecer los miembros que deseo cambiar (a través de los procedimientos de Propiedad). Las constantes de bandera se implementan como Enum. Entonces, por ejemplo, para elegir una hoja de cálculo para abrir, mi código podría verse así:
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 quisiera puedo cambiarlo con la propiedad InitDir.
Este es solo un ejemplo de cómo una clase puede ser muy beneficiosa en una aplicación de VBA.
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.
No veo por qué el criterio para VBA sería diferente de otro idioma, particularmente si se refiere a VB.NET.
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 .
Puede definir una clase contenedora sql en el acceso que sea más conveniente que los conjuntos de registros y los querydefs. Por ejemplo, si desea actualizar una tabla basada en un criterio en otra tabla relacionada, no puede usar uniones. Podrías crear un vb recorset y querydef 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 necesite más de 2 tablas, podría ser mejor utilizar clases para eso. Por ejemplo, incidencias de seguimiento de aplicaciones. El incidente tiene varios atributos que se mantendrán en varias tablas {usuarios y sus contactos o perfiles, descripción del incidente; seguimiento del estado; Listas de verificación para ayudar al oficial de soporte a responder el 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 ...
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.
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 :)
Utilizo las clases si quiero crear un paquete de código autoencapsulado que utilizaré en muchos proyectos de VBA para varios clientes.