2010-01-29 11 views
26

Estoy haciendo algunos programas de VBA en Excel 2007 y tengo un libro de trabajo donde se copiarán todas las hojas de datos, en otra hoja. La nueva hoja tendrá varias filas de encabezado, y me gustaría hacer un seguimiento de dónde se encuentran para no tener que encontrar palabras en ellas constantemente.¿Cuáles son los beneficios de usar Clases en VBA?

es la cosa más sencilla de usar clases y mantenerlos en funcionamiento, mientras que el documento Excel está abierto? ¿O esto hará que sea pesado y difícil de manejar, y debería seguir trabajando con subrutinas? ¿Cuáles son los beneficios con el uso de clases? No es como si tuviera varios objetos, solo hojas y validación en columnas.

Gracias!

Respuesta

6

Si hay muchas subrutinas o subrutinas son muy largas, la estructuración del código en las clases puede ayudar. Si solo hay un par de subrutinas, por ejemplo, cada una con solo 10 líneas de código, entonces esto se ha terminado. El beneficio de estructurar el código en las clases es que es más fácil de leer y cambiar cuando vuelves a la línea. Otra razón para estructurar el código en clases es si es probable que el código necesite cambiarse en la línea

69

La ventaja de utilizar clases en lugar de simplemente subrutinas es que las clases crean un nivel de abstracción que le permite escribir código más limpio. Es cierto que si nunca antes has usado clases en VBA, hay una curva de aprendizaje, pero creo que definitivamente vale la pena el tiempo para resolverlo.

Una indicación clave que debe cambiar a las clases es si constantemente agrega parámetros a sus funciones y subrutinas. En este caso, casi siempre es mejor usar clases.

he copiado una explicación de las clases de one of my previous Stack Overflow answers:


Aquí hay un largo ejemplo de cómo el uso de una clase que podría ayudarle. Aunque este ejemplo es extenso, le mostrará cómo algunos principios de programación orientada a objetos realmente pueden ayudarlo a limpiar su código.

En el editor de VBA, vaya al Insert > Class Module. En la ventana Propiedades (en la parte inferior izquierda de la pantalla de forma predeterminada), cambie el nombre del módulo a WorkLogItem. Agregue el código siguiente a la clase:

Option Explicit 

Private pTaskID As Long 
Private pPersonName As String 
Private pHoursWorked As Double 

Public Property Get TaskID() As Long 
    TaskID = pTaskID 
End Property 

Public Property Let TaskID(lTaskID As Long) 
    pTaskID = lTaskID 
End Property 

Public Property Get PersonName() As String 
    PersonName = pPersonName 
End Property 

Public Property Let PersonName(lPersonName As String) 
    pPersonName = lPersonName 
End Property 

Public Property Get HoursWorked() As Double 
    HoursWorked = pHoursWorked 
End Property 

Public Property Let HoursWorked(lHoursWorked As Double) 
    pHoursWorked = lHoursWorked 
End Property 

El código anterior nos dará un objeto inflexible de tipos que es específico a los datos con los que estamos trabajando. Cuando se utiliza matrices multidimensionales para almacenar sus datos, el código se parece a esto: arr(1,1) es el ID, arr(1,2) es el PersonName y arr(1,3) es la hoursWorked. Usando esa sintaxis, es difícil saber qué es qué. Supongamos que todavía cargas tus objetos en una matriz, pero en su lugar usa el WorkLogItem que creamos anteriormente. Este nombre, usted podría hacer arr(1).PersonName para obtener el nombre de la persona. Eso hace que tu código sea mucho más fácil de leer.

Sigamos con este ejemplo. En lugar de almacenar los objetos en el conjunto, intentaremos usar un collection.

A continuación, agregue un nuevo módulo de clase y llámelo ProcessWorkLog. Coloque el código siguiente en llegar:

Option Explicit 

Private pWorkLogItems As Collection 

Public Property Get WorkLogItems() As Collection 
    Set WorkLogItems = pWorkLogItems 
End Property 

Public Property Set WorkLogItems(lWorkLogItem As Collection) 
    Set pWorkLogItems = lWorkLogItem 
End Property 

Function GetHoursWorked(strPersonName As String) As Double 
    On Error GoTo Handle_Errors 
    Dim wli As WorkLogItem 
    Dim doubleTotal As Double 
    doubleTotal = 0 
    For Each wli In WorkLogItems 
     If strPersonName = wli.PersonName Then 
      doubleTotal = doubleTotal + wli.HoursWorked 
     End If 
    Next wli 

Exit_Here: 
    GetHoursWorked = doubleTotal 
     Exit Function 

Handle_Errors: 
     'You will probably want to catch the error that will ' 
     'occur if WorkLogItems has not been set ' 
     Resume Exit_Here 


End Function 

La clase anterior se va a utilizar para "hacer algo" con un colleciton de WorkLogItem. Inicialmente, simplemente lo configuramos para contar la cantidad total de horas trabajadas. Probemos el código que escribimos.Cree un nuevo Módulo (no un módulo de clase esta vez, solo un módulo "regular"). Pegar el código siguiente en el módulo:

Option Explicit 

Function PopulateArray() As Collection 
    Dim clnWlis As Collection 
    Dim wli As WorkLogItem 
    'Put some data in the collection' 
    Set clnWlis = New Collection 

    Set wli = New WorkLogItem 
    wli.TaskID = 1 
    wli.PersonName = "Fred" 
    wli.HoursWorked = 4.5 
    clnWlis.Add wli 

    Set wli = New WorkLogItem 
    wli.TaskID = 2 
    wli.PersonName = "Sally" 
    wli.HoursWorked = 3 
    clnWlis.Add wli 

    Set wli = New WorkLogItem 
    wli.TaskID = 3 
    wli.PersonName = "Fred" 
    wli.HoursWorked = 2.5 
    clnWlis.Add wli 

    Set PopulateArray = clnWlis 
End Function 

Sub TestGetHoursWorked() 
    Dim pwl As ProcessWorkLog 
    Dim arrWli() As WorkLogItem 
    Set pwl = New ProcessWorkLog 
    Set pwl.WorkLogItems = PopulateArray() 
    Debug.Print pwl.GetHoursWorked("Fred") 

End Sub 

En el código anterior, PopulateArray() simplemente crea una colección de WorkLogItem. En su código real, puede crear una clase para analizar sus hojas de Excel o sus objetos de datos para llenar una colección o una matriz.

El código TestGetHoursWorked() simplemente muestra cómo se usaron las clases. Observa que ProcessWorkLog se crea una instancia como un objeto. Después de que se crea una instancia, una colección de WorkLogItem se convierte en parte del objeto pwl. Usted nota esto en la línea Set pwl.WorkLogItems = PopulateArray(). A continuación, simplemente llamamos a la función que escribimos que actúa sobre la colección WorkLogItems.

¿Por qué es esto útil?

Supongamos que sus datos cambian y desea agregar un nuevo método. Supongamos que su WorkLogItem ahora incluye un campo para HoursOnBreak y desea agregar un nuevo método para calcularlo.

Todo lo que necesita hacer es añadir un alojamiento a WorkLogItem así:

Private pHoursOnBreak As Double 

Public Property Get HoursOnBreak() As Double 
    HoursOnBreak = pHoursOnBreak 
End Property 

Public Property Let HoursOnBreak(lHoursOnBreak As Double) 
    pHoursOnBreak = lHoursOnBreak 
End Property 

Por supuesto, tendrá que cambiar su método para poblar su colección (el método de muestreo que utilicé fue PopulateArray(), pero probablemente deberías tener una clase separada solo para esto). Entonces sólo tiene que añadir el nuevo método a la clase ProcessWorkLog:

Function GetHoursOnBreak(strPersonName As String) As Double 
    'Code to get hours on break 
End Function 

Ahora, si queríamos actualizar nuestro método TestGetHoursWorked() para volver resultado de GetHoursOnBreak, lo único que tendríamos que hacer lo que añadir la siguiente línea:

Debug.Print pwl.GetHoursOnBreak("Fred") 

Si pasó una serie de valores que representaban sus datos, tendría que encontrar cada lugar en su código donde utilizó las matrices y luego actualizarlas en consecuencia. Si usa clases (y sus objetos instanciados), puede actualizar su código mucho más fácilmente para trabajar con cambios. Además, cuando permite que la clase se consuma de múltiples maneras (tal vez una función necesita solo 4 de las propiedades de los objetos, mientras que otra función necesitará 6), todavía pueden hacer referencia al mismo objeto. Esto evita tener múltiples matrices para diferentes tipos de funciones.

Para obtener más información, me gustaría altamente recomendamos obtener una copia de VBA Developer's Handbook, 2nd edition. El libro está lleno de excelentes ejemplos, mejores prácticas y toneladas de código de muestra. Si invierte mucho tiempo en VBA para un proyecto serio, vale la pena ver este libro.

+7

+1, GRAN respuesta. Claro, fresco y muy útil para todos. –

+2

+1 para el Manual del desarrollador de VBA! –

+0

Todavía útil 5 años después, ¡gracias Ben! +1 de mi parte – FreeMan

3

Hay otra cosa que podría agregar a las ventajas que otros colaboradores han establecido (lo siento si es en algún lugar de la excelente respuesta de Ben McCormack y me lo perdí). Las clases pueden tener sus usos si es probable que su script VBA sea reprogramado en algún momento.

Por ejemplo, estoy diseñando una especie de sistema de gestión de pedidos. Ha de ser utilizado por varios colegas durante bastante tiempo, pero puede necesitar reprogramación si las reglas de pedido cambian. Por lo tanto, he diseñado una clase de stock básico, que reúne toda la información sobre un artículo en stock. Sin embargo, las reglas sobre cómo se analizan estos datos para cualquier orden se escriben en sub rutinas fácilmente accesibles y bien comentadas.Al hacer esto, espero que los futuros programadores de VBA puedan cambiar fácilmente las reglas matemáticas mediante las cuales se generan órdenes, sin tener que lidiar con cómo se recopilan todos los datos sobre un artículo en particular (todo esto se hace mediante subrutinas y funciones dentro de la clase , que se activan cuando a la clase se le entrega un número de inventario). Las propiedades públicas de la Clase también son recogidas por intellisense, lo que permite que el siguiente programador, así como usted mismo, lo tengan más fácil.

Supongo que el punto es que las clases pueden hacer la vida más fácil para los usuarios posteriores de esta manera si que codifican un conjunto básico de información, o algún objeto conceptual, que siempre es probable que sea relevante para el contexto del programa de utilizar.

Cuestiones relacionadas