2012-09-12 24 views
14

Mi sono divertito a misurare i tempi di esecuzione del codice per misurare le differenze tra l'esecuzione dei miei script localmente e il mio server. A un certo punto ho dimenticato di disabilitare screen updating ed ero grato di non essere sensibile alle luci lampeggianti prima di pensarci in modo più dettagliato:Effetto dell'aggiornamento dello schermo

Quando ho iniziato a usare VBA ho sempre pensato che fosse usato solo in modo che non spaventare gli utenti finali pensando che il loro PC stesse per schiantarsi. Quando ho iniziato a leggere di più per migliorare l'efficienza del tuo codice, ho capito a cosa serviva, ma quanto di un effetto ha lo screen updating sul tempo di esecuzione dei codici?

+4

A seconda di cosa sta facendo il codice, l'impostazione di "Application.Calculation" su "manual" spesso ti darà anche un grande incremento di velocità. In genere esegui entrambe le operazioni per una macro con esecuzione prolungata. Non dimenticare di resettare il calcolo, è un'impostazione persistente. –

+1

Inoltre, con l'esecuzione di 'Screenupdating' disattivato è possibile consentire all'utente di conoscere l'avanzamento tramite' Application.Statusbar = '. Quindi imposta 'False' per riportarlo alla normalità. Alcune persone hanno bisogno di vedere i progressi altrimenti pensano che il loro computer si sia bloccato e costretto a chiudere tutto. – Rory

+0

Ho anche letto che il formato dati predefinito in Excel è effettivamente Valuta, quindi è preferibile utilizzare Valuta come valore di dati anziché Double quando possibile per evitare la conversione dei dati. –

risposta

23

L'disattivazione dell'aggiornamento dello schermo fa solo la differenza rispetto al tempo di esecuzione se il codice interagisce con Excel in un modo che provoca modifiche al contenuto dello schermo. Più la quantità di schermo cambia, maggiore sarà l'impatto. Le altre risposte postate dimostrano adeguatamente questo.

Altre impostazioni dell'applicazione che possono fare la differenza per il tempo di esecuzione sono Calcolo e Gestione eventi. Utilizzare questo modello codice come punto di partenza (il gestore di errori assicura che queste proprietà vengono riattivati ​​al termine del sub, anche se gli errori)

Sub YourSub() 
    On Error GoTo EH 

    Application.ScreenUpdating = False 
    Application.Calculation = xlCalculationManual 
    Application.EnableEvents = False 

    ' Code here 

CleanUp: 
    On Error Resume Next 
    Application.ScreenUpdating = True 
    Application.Calculation = xlCalculationAutomatic 
    Application.EnableEvents = True 
Exit Sub 
EH: 
    ' Do error handling 
    GoTo CleanUp 
End Sub 

Altre tecniche esistenti che possono fornire anche un miglioramento maggiore esecuzione velocità.

Il più utili sono

  1. Evitare Select, Activate e ActiveCell/Sheet/Workbook il più possibile. Invece dichiarare e assegnare variabili e fare riferimento a quelle.
  2. Quando si fa riferimento a intervalli di grandi dimensioni, copiare i dati di intervallo su un array variante per l'elaborazione e copiare nuovamente il risultato nell'intervallo dopo.
  3. Utilizzare Range.SpecialCells, Range.Find e Range.AutoFilter per limitare il numero di celle a cui si fa riferimento.

Ci sono molti esempi di queste tecniche su SO.

+1

Vuoi che il 'CleanUp:' faccia l'opposto di ciò che fa attualmente destra? ;) – enderland

+0

@enderland Oops ... –

2

In primo luogo ho usato lo script scritto da Richie (UK) Post # 7 Here

'semplicemente scorre un ciclo modificando il valore di i in una cella. L'ho modificato leggermente in modo che giri 10.000 volte e lo eseguo 10 volte per la dimensione del campione.

Qual è l'effetto dell'aggiornamento dello schermo sulla velocità di esecuzione dei miei codici?

Queste sono le lunghezze di esecuzione quando Screen Updating è stato disattivato e abilitato:

Disabled Enabled 
0.61909653 2.105066913 
0.619555829 2.106865363 
0.620805767 2.106866315 
0.625528325 2.102403315 
0.625319976 2.0991179 
0.621287448 2.105103142 
0.621540236 2.101392665 
0.624537531 2.106866716 
0.620401789 2.109004449 

Come si può vedere ci vogliono quasi 3,5 volte più a lungo per eseguire il codice quando Screen Updating non è disattivato.

Entrambi questi codici sono stati evidenziati utilizzando il pulsante Esegui nell'editor VB, anziché "guardare" il foglio di calcolo.

2 linee semplici all'inizio e alla fine del codice:

Application.ScreenUpdating = False 
Application.ScreenUpdating = True 

Ma, si può avere un grande effetto sulla efficienza della vostra esecuzione!

Nota: Ovviamente i vantaggi di Screen Updating saranno ben noti a molti qui, ma questo può essere di beneficio per i principianti e lo trovo interessante per visualizzare i numeri!

6

Se si desidera visualizzare un esempio abbastanza chiaro del motivo per cui ScreenUpdating è importante, eseguire il seguente codice. In Excel 2011 ci vogliono circa 45 volte più a lungo per eseguire questo swap senza ScreenUpdating = false! Questa è una differenza enorme nel tempo.

Sub testScreenUpdating() 

    Dim i As Integer 
    Dim numbSwitches As Integer 
    Dim results As String 

    'swap between sheets this number of times 
    numbSwitches = 1000 

    'keep track of time 
    Dim startTime As Double 
    startTime = Time 

    'swap between sheets 1/2 (need both sheets or this will crash) 
    For i = 1 To numbSwitches 
     Sheets(1 + (i Mod 2)).Select 
    Next i 

    'get results 
    results = "Screen Updating not disabled: " & Format(Time - startTime, "hh:mm:ss") & " seconds" 
    startTime = Time 

    'scenario 2 - screenupdating disabled 

    Application.ScreenUpdating = False 

    'swap between sheets 1/2 (need both sheets or this will crash) 
    For i = 1 To numbSwitches 
     Sheets(1 + (i Mod 2)).Select 
    Next i 

    Application.ScreenUpdating = True 

    'get results for part two 
    results = results & vbCrLf & "Screen Updating IS disabled: " & Format(Time - startTime, "hh:mm:ss") & " seconds" 

    'show results 
    MsgBox results 


End Sub 

Inoltre, già che siamo in tema di modi per aumentare l'efficienza, un altro punto chiave è che Select, Selection, e Activate sono raramente (se non mai) necessario. Quando si registrano i macro, verranno sempre utilizzati, ma ci sono pochissime situazioni in cui è necessario utilizzarli effettivamente nel codice. Allo stesso modo, qualsiasi cosa con Active nel titolo (ad esempio ActiveCell) è normalmente un'indicazione che si avrà codice più lento perché si presume che si selezionino le celle.

Si può quasi sempre fare riferimento a celle/fogli di lavoro in modo specifico ed evitare di selezionare.Ad esempio:

msgbox (Worksheets(1).Range("A1").value) 

funzionerà indipendentemente dal fatto che si sia attualmente sul primo foglio di lavoro. Un nuovo errore VBA comune è quello di fare qualcosa di più simile:

Worksheets(1).Select 
msgbox (Range("A1").value) 

che è un passaggio non necessario.

Questo aggiunge un tempo significativo al codice in runtime.

+0

Ben detto. Alistair, se desideri alcuni esempi eccellenti su come evitare di selezionare, vedi la risposta di Chris Nielsen: http://stackoverflow.com/a/10717999/138938 –

0

C'è una cosa importante da sapere sull'aggiornamento dello schermo che non ho visto in nessuna risposta precedente. Dal mio test, scopro che l'aggiornamento dello schermo di spegnimento e acceso richiede circa 15ms (testato in C# tramite Excel Interop). Tienilo a mente se eseguirai qualsiasi cosa che richiederebbe meno tempo. E dopotutto non attivare o disattivare l'aggiornamento dello schermo più volte in un ciclo. Quello sarebbe un vero killer delle prestazioni.

E un'altra nota (che probabilmente non vuoi sentire) se vuoi usare rapidamente C++. In genere è da 5 a 10 volte più veloce (non prendermi qui dipende da cosa realmente fai) rispetto a VBA.

0

so che è un vecchio thread, ma:

1) Non impostare ScreenUpdating = true, ma ricordate e riportarlo al suo vecchio valore. 2) La modifica delle cartelle di lavoro ripristina anche lo Screenupdating.

Problemi correlati