2010-01-29 15 views
26

Sto facendo qualche programmazione VBA in Excel 2007 e ho una cartella di lavoro da cui copiare tutti i fogli di dati, in un altro foglio. Il nuovo foglio avrà diverse righe di intestazione e vorrei tenere traccia di dove si trovano, quindi non devo trovare continuamente parole in esse.Quali sono i vantaggi dell'utilizzo di Classi in VBA?

È la cosa più semplice usare le classi e mantenerle attive mentre il documento excel è aperto? O lo renderà pesante e difficile da gestire, e dovrei continuare a lavorare con le subroutine? Quali sono i vantaggi nell'utilizzo delle classi? Non è come se avessi diversi oggetti, solo fogli e validazione su colonne.

Grazie!

risposta

6

Se ci sono molte subroutine o subroutine molto lunghe, allora può essere utile strutturare il codice nelle classi. Se ci sono solo un paio di subroutine, diciamo, ognuna delle quali è composta da solo 10 righe di codice, allora questo è over kill. Il vantaggio di strutturare il codice nelle classi è che è più facile da leggere e modificare quando si torna indietro. Quindi un'altra ragione per strutturare il codice in classi è se è probabile che il codice debba cambiare linea

69

Il vantaggio di utilizzare classi anziché solo subroutine è che le classi creano un livello di astrazione che consente di scrivere codice più pulito. Certo, se non hai mai usato le lezioni prima in VBA, c'è una curva di apprendimento, ma credo che valga sicuramente il tempo di capirlo.

Un'indicazione chiave che è necessario passare alle classi è se si aggiungono costantemente parametri alle proprie funzioni e subroutine. In questo caso, è quasi sempre meglio usare le classi.

Ho copiato una spiegazione di classi da one of my previous Stack Overflow answers:


Ecco un lungo esempio di come utilizzare una classe potrebbe aiutarvi. Sebbene questo esempio sia lungo, ti mostrerà come alcuni principi di programmazione orientata agli oggetti possono davvero aiutarti a ripulire il tuo codice.

Nell'editor VBA, andare a Insert > Class Module. Nella finestra Proprietà (in basso a sinistra dello schermo per impostazione predefinita), modificare il nome del modulo in WorkLogItem. Aggiungere il seguente codice alla classe:

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 

Il codice di cui sopra ci darà un oggetto fortemente tipizzato che è specifico per i dati con i quali stiamo lavorando. Quando si utilizzano gli array a più dimensioni per archiviare i dati, il codice è simile al seguente: arr(1,1) è l'ID, arr(1,2) è il PersonName e arr(1,3) è HoursWorked. Usando questa sintassi, è difficile sapere cosa sia cosa. Supponiamo che tu continui a caricare i tuoi oggetti in un array, ma invece usi lo WorkLogItem che abbiamo creato sopra. Con questo nome, potresti ottenere arr(1).PersonName per ottenere il nome della persona. Questo rende il tuo codice molto più facile da leggere.

Continuiamo a muoverci con questo esempio. Invece di archiviare gli oggetti nell'array, proveremo a utilizzare collection.

Successivamente, aggiungere un nuovo modulo di classe e chiamarlo ProcessWorkLog. Inserire il seguente codice in là:

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 classe di cui sopra sta per essere usato per "fare qualcosa" con un colleciton di WorkLogItem. Inizialmente, l'abbiamo appena impostato per contare il numero totale di ore lavorate. Proviamo il codice che abbiamo scritto.Crea un nuovo modulo (non un modulo di classe questa volta, solo un modulo "normale"). Incollare il seguente codice nel modulo:

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 

Nel codice precedente, PopulateArray() crea semplicemente un insieme di WorkLogItem. Nel codice reale, è possibile creare classi per analizzare i fogli di Excel o gli oggetti dati per riempire una raccolta o un array.

Il codice TestGetHoursWorked() mostra semplicemente come sono state utilizzate le classi. Si noti che ProcessWorkLog viene creato come un oggetto. Dopo averlo istanziato, una raccolta di WorkLogItem diventa parte dell'oggetto pwl. Si nota questo nella riga Set pwl.WorkLogItems = PopulateArray(). Successivamente, chiamiamo semplicemente la funzione che abbiamo scritto che agisce sulla collezione WorkLogItems.

Perché è utile?

Supponiamo che i dati cambino e che tu voglia aggiungere un nuovo metodo. Supponiamo che il tuo WorkLogItem includa ora un campo per HoursOnBreak e tu voglia aggiungere un nuovo metodo per calcolarlo.

Tutto quello che dovete fare è aggiungere un alloggio ai WorkLogItem in questo modo:

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 

Naturalmente, è necessario modificare il metodo per la compilazione vostra collezione (il metodo di esempio che ho usato era PopulateArray(), ma probabilmente dovresti avere una classe separata solo per questo). Poi basta aggiungere il nuovo metodo per la classe ProcessWorkLog:

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

Ora, se volessimo aggiornare il nostro metodo TestGetHoursWorked() al risultato di GetHoursOnBreak tornare, tutti avremmo dovuto fare come aggiungere la seguente riga:

Debug.Print pwl.GetHoursOnBreak("Fred") 

Se passavi in ​​una serie di valori che rappresentavano i tuoi dati, dovresti trovare ogni posizione nel codice in cui hai utilizzato gli array e quindi aggiornarli di conseguenza. Se invece usi le classi (e i loro oggetti istanziati), puoi molto più facilmente aggiornare il tuo codice per lavorare con le modifiche. Inoltre, quando consenti alla classe di essere consumata in più modi (forse una funzione ha bisogno solo di 4 delle proprietà degli oggetti mentre un'altra funzione ne avrà bisogno 6), possono comunque fare riferimento allo stesso oggetto. Questo ti impedisce di disporre di più array per diversi tipi di funzioni.

Per ulteriore lettura, vorrei altamente consiglia di ottenere una copia di VBA Developer's Handbook, 2nd edition. Il libro è pieno di ottimi esempi e best practice e tonnellate di codice di esempio. Se investi molto tempo in VBA per un progetto serio, vale la pena dedicare tempo a esaminare questo libro.

+7

+1, GRANDE risposta. Chiaro, nitido e molto utile per tutti. –

+2

+1 per il manuale dello sviluppatore VBA! –

+0

Ancora utile 5 anni dopo, grazie Ben! +1 da me. – FreeMan

3

C'è un'altra cosa che potresti aggiungere ai vantaggi che altri contributori hanno affermato (scusa se è da qualche parte nell'eccellente risposta di Ben McCormack e l'ho perso). Le classi possono avere i loro usi se il tuo script VBA rischia di essere riprogrammato ad un certo punto.

Per esempio, sto progettando una sorta di sistema di gestione degli ordini. Verrà utilizzato da diversi colleghi per un certo periodo di tempo, ma potrebbe essere necessario riprogrammare le modifiche delle regole di ordinazione. Ho quindi progettato una classe di articoli di base, che raccoglie tutte le informazioni su un articolo di riserva. Le regole su come questi dati vengono analizzati per qualsiasi ordine sono, tuttavia, scritti in sub-routine facilmente accessibili e ben commentate.In questo modo, spero che i futuri programmatori VBA possano facilmente cambiare le regole matematiche con cui vengono generati gli ordini, senza dover gestire il modo in cui tutti i dati sono raccolti su un particolare articolo di magazzino (tutto fatto con subroutine e funzioni all'interno della classe , che vengono attivati ​​quando alla classe viene consegnato un numero di magazzino). Le proprietà pubbliche di una Classe vengono anche rilevate da intellisense, consentendo al programmatore successivo, oltre a te stesso, di avere un momento più semplice.

Credo che il punto è che le classi possono rendere la vita più facile per gli utenti più avanti in questo modo se codificano alcuni set di base di dati, o di qualche oggetto concettuale, che è sempre probabile che sia rilevante per il contesto del programma di uso.

Problemi correlati