2012-09-12 11 views
14

He estado jugando a medir los tiempos de ejecución de código para medir las diferencias entre la ejecución de mis scripts localmente y en mi servidor. En un momento me olvidé de deshabilitar screen updating y me alegré de no ser sensible a las luces intermitentes antes de pensar en ello con más detalle:Efecto de la actualización de pantalla

Cuando comencé a usar VBA siempre asumí que solo se usaba para que no funcionara asustar a los usuarios finales haciéndoles creer que su PC estaba a punto de colapsar. Cuando comencé a leer más sobre cómo mejorar la eficiencia de tu código, entendí para qué era pero ¿qué efecto tiene realmente screen updating en el tiempo de ejecución de tus códigos?

+4

Dependiendo de lo que esté haciendo su código, establecer 'Application.Calculation' en" manual "a menudo también le dará un impulso de gran velocidad. Típicamente harías ambas cosas para una macro de larga ejecución. No olvide restablecer el cálculo, es una configuración persistente. –

+1

Aslo, con la ejecución de 'Screenupdating' desactivada, puede informar al usuario del progreso mediante' Application.Statusbar = '. Luego configure 'False' para regresarlo a la normalidad. Algunas personas necesitan ver el progreso; de lo contrario, creen que su computadora se ha congelado y obligan a cerrar todo. – Rory

+0

También he leído que el formato de datos predeterminado en Excel es en realidad Moneda, por lo que es mejor usar Divisa como valor de datos en lugar de Doble cuando sea posible para evitar la conversión de datos. –

Respuesta

23

Desactivar la actualización de la pantalla solo hará una diferencia en el tiempo de ejecución si el código interactúa con Excel de una manera que causa cambios en el contenido de la pantalla. Cuanto más ralla la cantidad de pantalla cambia, mayor será el impacto. Las otras respuestas publicadas demuestran acertadamente esto.

Otras configuraciones de aplicaciones que pueden marcar la diferencia en el tiempo de ejecución son el cálculo y el manejo de eventos. Utilice esta plantilla de código como punto de partida (el gestor de errores asegura que estas propiedades se convierten de nuevo en al final de la sub, incluso si los errores) existen

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 

Otras técnicas que pueden proporcionar incluso una mayor mejora en la ejecución velocidad.

Los más útiles incluyen

  1. Evitar Select, Activate y ActiveCell/Sheet/Workbook tanto como sea posible. En su lugar, declare y asigne variables y haga referencia a ellas.
  2. Al hacer referencia a rangos grandes, copie los datos de rango en una matriz de variantes para procesarlos y copie el resultado nuevamente en el rango siguiente.
  3. Utilice Range.SpecialCells, Range.Find y Range.AutoFilter para limitar el número de celdas a las que se hace referencia.

Hay muchos ejemplos de estas técnicas en SO.

+1

Desea que su 'CleanUp:' haga lo contrario de lo que hace actualmente. ¿derecho? ;) – enderland

+0

@enderland Oops ... –

2

En primer lugar He estado usando el guión escrito por Richie (Reino Unido) Anuncio # 7 Here

simplemente itera a través de un bucle cambiando el valor de i en una célula. Lo he cambiado ligeramente para que gire 10.000 veces y lo ejecute 10 veces para el tamaño de muestra.

¿Cuál es el efecto de la actualización de la pantalla sobre la velocidad de ejecución de mis códigos?

Estas son las longitudes de ejecución cuando Screen Updating fue desactivado y activado:

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 

Como se puede ver que se necesita casi 3,5 veces más tiempo para ejecutar el código cuando Screen Updating no se desactiva.

Ambos códigos se superaron con el botón Ejecutar en el editor VB, en lugar de "mirar" la hoja de cálculo.

2 líneas simples al principio y al final de su código:

Application.ScreenUpdating = False 
Application.ScreenUpdating = True 

embargo, pueden tener un gran efecto sobre la eficiencia de su ejecución!

Nota: Obviamente las ventajas de Screen Updating serán bien conocidos para muchos aquí, pero esto puede ser de beneficio para los principiantes y me parece interesante para ver los números!

6

Si desea ver un ejemplo bastante drástico de por qué ScreenUpdating es importante, ejecute el siguiente código. ¡Se tarda aproximadamente 45 veces más en Excel 2011 para que pueda ejecutar este intercambio sin ScreenUpdating = false! Esta es una gran diferencia en el tiempo.

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 

También, ya que estamos en el tema de las maneras de aumentar la eficiencia, otro punto clave es que Select, Selection y Activate son rara vez (o nunca) es necesario. Cuando graba macros, siempre las usará, pero hay muy pocas situaciones en las que necesite utilizarlas en el código. Del mismo modo, cualquier cosa con Active en el título (como ActiveCell) normalmente es una indicación de que tendrá un código más lento porque presumiblemente está seleccionando celdas.

Casi siempre puede consultar celdas/hojas de trabajo específicamente y evitar seleccionar.Por ejemplo:

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

funcionará independientemente de si se encuentra actualmente en la primera hoja de cálculo. Un nuevo error común de VBA es hacer algo más como:

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

que es un paso innecesario.

Esto agrega un tiempo significativo a los tiempos de ejecución del código.

+0

Bien dicho. Alistair, si desea ejemplos excelentes sobre cómo evitar la selección, consulte la respuesta de Chris Nielsen: http://stackoverflow.com/a/10717999/138938 –

0

Hay una cosa importante que saber acerca de la actualización de la pantalla que no he visto en ninguna respuesta anterior. Según mi propia prueba, descubrí que activar y desactivar la actualización de la pantalla lleva unos 15 ms (probado en C# mediante Excel Interop). Tenga eso en cuenta si ejecutará algo que tomaría menos tiempo. Y después de todo, no active/desactive la actualización de la pantalla muchas veces en algún bucle. Eso sería un verdadero asesino de rendimiento.

Y una nota más (que probablemente no desee escuchar) si lo desea, use C++ rápidamente. Por lo general, es 5 a 10 veces más rápido (no me atrape aquí, depende de lo que realmente haga) que VBA.

0

sé que es un hilo viejo, pero:

1) No coloque ScreenUpdating = true, pero remeber y la pusieron de nuevo a su valor anterior. 2) Cambiar libros de trabajo también restablecerá Screenupdating.

Cuestiones relacionadas