2011-03-03 65 views
47

Estoy haciendo una aplicación de Excel que necesita mucha actualización de datos desde una base de datos, por lo que lleva tiempo. Quiero hacer una barra de progreso en una forma de usuario y aparece cuando los datos se actualizan. La barra que quiero es solo una pequeña barra azul que se mueve hacia la derecha y hacia la izquierda y se repite hasta que se complete la actualización, no se necesita un porcentaje. Sé que debo usar el control progressbar, pero lo intenté por algún tiempo pero no puedo hacerlo.Barra de progreso en VBA Excel

EDITAR: Mi problema es con el control progressbar, no puedo ver el progreso de la barra, simplemente se completa cuando aparece el formulario. Yo uso un ciclo y DoEvent pero eso no está funcionando. Además, quiero que el proceso se repita, no solo una vez.

+2

"intentado durante algún tiempo, pero no puede hacerlo" - nos muestran lo que ha logrado hacer, cuáles son los problemas y nos Trataremos de ayudarte –

+1

thx por consejo, mira la edición – darkjh

Respuesta

30

En el pasado, con los proyectos de VBA, he usado un control de etiqueta con el fondo de color y ajuste el tamaño según el progreso. Algunos ejemplos con enfoques similares se pueden encontrar en los siguientes enlaces:

  1. http://oreilly.com/pub/h/2607
  2. http://www.ehow.com/how_7764247_create-progress-bar-vba.html
  3. http://spreadsheetpage.com/index.php/tip/displaying_a_progress_indicator/

Esta es la que utiliza autoshapes de Excel:

http://www.andypope.info/vba/pmeter.htm

+1

thx intentaré de esta manera – darkjh

+1

@darkjh: De nada. Al ver que eres nuevo, recuerda aceptar y/o votar si esto responde a tu pregunta o es útil. Gracias. – Matt

8
============== This code goes in Module1 ============ 

Sub ShowProgress() 
    UserForm1.Show 
End Sub 

============== Module1 Code Block End ============= 

Crear un botón en una hoja de cálculo; botón de mapa para "ShowProgress" macro

Crear una UserForm1 con 2 botones, barras de progreso, barra de la caja, cuadro de texto:

UserForm1 = canvas to hold other 5 elements 
CommandButton2 = Run Progress Bar Code; Caption:Run 
CommandButton1 = Close UserForm1; Caption:Close 
Bar1 (label) = Progress bar graphic; BackColor:Blue 
BarBox (label) = Empty box to frame Progress Bar; BackColor:White 
Counter (label) = Display the integers used to drive the progress bar 

======== Attach the following code to UserForm1 ========= 

Option Explicit 

' This is used to create a delay to prevent memory overflow 
' remove after software testing is complete 

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 

Private Sub UserForm_Initialize() 

    Bar1.Tag = Bar1.Width 
    Bar1.Width = 0 

End Sub 
Sub ProgressBarDemo() 
    Dim intIndex As Integer 
    Dim sngPercent As Single 
    Dim intMax As Integer 
    '============================================== 
    '====== Bar Length Calculation Start ========== 

    '-----------------------------------------------' 
    ' This section is where you can use your own ' 
    ' variables to increase bar length.    ' 
    ' Set intMax to your total number of passes  ' 
    ' to match bar length to code progress.   ' 
    ' This sample code automatically runs 1 to 100 ' 
    '-----------------------------------------------' 
    intMax = 100 
    For intIndex = 1 To intMax 
     sngPercent = intIndex/intMax 
     Bar1.Width = Int(Bar1.Tag * sngPercent) 
     Counter.Caption = intIndex 


    '======= Bar Length Calculation End =========== 
    '============================================== 


DoEvents 
     '------------------------ 
     ' Your production code would go here and cycle 
     ' back to pass through the bar length calculation 
     ' increasing the bar length on each pass. 
     '------------------------ 

'this is a delay to keep the loop from overrunning memory 
'remove after testing is complete 
     Sleep 10 

    Next 

End Sub 
Private Sub CommandButton1_Click() 'CLOSE button 

Unload Me 

End Sub 
Private Sub CommandButton2_Click() 'RUN button 

     ProgressBarDemo 

End Sub 

================= UserForm1 Code Block End ===================== 

============== This code goes in Module1 ============= 

Sub ShowProgress() 
    UserForm1.Show 
End Sub 

============== Module1 Code Block End ============= 
+0

¡Esta es una buena solución! – Stephan

106

A veces un simple mensaje en la barra de estado es suficiente:

Message in Excel status bar using VBA

Ésta es very simple to implement:

Dim x    As Integer 
Dim MyTimer   As Double 

'Change this loop as needed. 
For x = 1 To 50 
    ' Do stuff 
    Application.StatusBar = "Progress: " & x & " of 50: " & Format(x/50, "0%") 
Next x 

Application.StatusBar = False 
+4

Me alegro de ver esto. Fue una idea mucho mejor para mí que fingir una barra de progreso. – atomicules

+1

Como soy, simple y efectivo. – Sean

+0

Fantástica respuesta. +1 – Caltor

41

Aquí hay otro ejemplo que usa StatusBar como una barra de progreso.

Al usar algunos caracteres Unicode, puede imitar una barra de progreso. 9608 - 9615 son los códigos que probé para las barras. Solo seleccione uno de acuerdo a la cantidad de espacio que desea mostrar entre las barras. Puede establecer la longitud de la barra cambiando NUM_BARS. Además, al usar una clase, puede configurarla para que maneje la inicialización y la liberación de StatusBar automáticamente. Una vez que el objeto sale del alcance, se limpiará automáticamente y liberará StatusBar nuevamente a Excel.

' Class Module - ProgressBar 
Option Explicit 

Private statusBarState As Boolean 
Private enableEventsState As Boolean 
Private screenUpdatingState As Boolean 
Private Const NUM_BARS As Integer = 50 
Private Const MAX_LENGTH As Integer = 255 
Private BAR_CHAR As String 
Private SPACE_CHAR As String 

Private Sub Class_Initialize() 
    ' Save the state of the variables to change 
    statusBarState = Application.DisplayStatusBar 
    enableEventsState = Application.EnableEvents 
    screenUpdatingState = Application.ScreenUpdating 
    ' set the progress bar chars (should be equal size) 
    BAR_CHAR = ChrW(9608) 
    SPACE_CHAR = ChrW(9620) 
    ' Set the desired state 
    Application.DisplayStatusBar = True 
    Application.ScreenUpdating = False 
    Application.EnableEvents = False 
End Sub 

Private Sub Class_Terminate() 
    ' Restore settings 
    Application.DisplayStatusBar = statusBarState 
    Application.ScreenUpdating = screenUpdatingState 
    Application.EnableEvents = enableEventsState 
    Application.StatusBar = False 
End Sub 

Public Sub Update(ByVal Value As Long, _ 
        Optional ByVal MaxValue As Long= 0, _ 
        Optional ByVal Status As String = "", _ 
        Optional ByVal DisplayPercent As Boolean = True) 

    ' Value   : 0 to 100 (if no max is set) 
    ' Value   : >=0 (if max is set) 
    ' MaxValue  : >= 0 
    ' Status   : optional message to display for user 
    ' DisplayPercent : Display the percent complete after the status bar 

    ' <Status> <Progress Bar> <Percent Complete> 

    ' Validate entries 
    If Value < 0 Or MaxValue < 0 Or (Value > 100 And MaxValue = 0) Then Exit Sub 

    ' If the maximum is set then adjust value to be in the range 0 to 100 
    If MaxValue > 0 Then Value = WorksheetFunction.RoundUp((Value * 100)/MaxValue, 0) 

    ' Message to set the status bar to 
    Dim display As String 
    display = Status & " " 

    ' Set bars 
    display = display & String(Int(Value/(100/NUM_BARS)), BAR_CHAR) 
    ' set spaces 
    display = display & String(NUM_BARS - Int(Value/(100/NUM_BARS)), SPACE_CHAR) 

    ' Closing character to show end of the bar 
    display = display & BAR_CHAR 

    If DisplayPercent = True Then display = display & " (" & Value & "%) " 

    ' chop off to the maximum length if necessary 
    If Len(display) > MAX_LENGTH Then display = Right(display, MAX_LENGTH) 

    Application.StatusBar = display 
End Sub 

Uso de la muestra:

Dim progressBar As New ProgressBar 

For i = 1 To 100 
    Call progressBar.Update(i, 100, "My Message Here", True) 
    Application.Wait (Now + TimeValue("0:00:01")) 
Next 
2
Sub ShowProgress() 
' Author : Marecki 
    Const x As Long = 150000 
    Dim i&, PB$ 

    For i = 1 To x 
    PB = Format(i/x, "00 %") 
    Application.StatusBar = "Progress: " & PB & " >>" & String(Val(PB), Chr(183)) & String(100 - Val(PB), Chr(32)) & "<<" 
    Application.StatusBar = "Progress: " & PB & " " & ChrW$(10111 - Val(PB)/11) 
    Application.StatusBar = "Progress: " & PB & " " & String(100 - Val(PB), ChrW$(9608)) 
    Next i 

    Application.StatusBar = "" 
End SubShowProgress 
0

Niza forma progressbar diálogo i buscaba. progressbar from alainbryden

muy fácil de usar, y se ve bien.

edición: enlace sólo funciona para premium miembros ahora:/

here es agradable clase alternativa.

6

El control de etiquetas que cambia de tamaño es una solución rápida. Sin embargo, la mayoría de las personas terminan creando formularios individuales para cada una de sus macros. Usé la función DoEvents y una forma no modal para usar un único formulario para todas sus macros.

Aquí es un post que escribí al respecto: http://strugglingtoexcel.wordpress.com/2014/03/27/progress-bar-excel-vba/

Todo lo que tiene que hacer es importar la forma y un módulo en sus proyectos, y llamar a la barra de progreso con: Call modProgress.ShowProgress (actionindex, TotalActions , Título .....)

Espero que esto ayude.

+1

También encontré el botón "Anular" en el cuadro de diálogo muy útil, gracias. –

+1

Hola Thomas. Todos queremos detener un ciclo a voluntad, es por eso que codifiqué eso. Gracias por notarlo. Que tengas un gran día. –

2

Me encantan todas las soluciones publicadas aquí, pero lo resolví usando el formato condicional como una barra de datos basada en porcentaje.

Conditional Formatting

Esto se aplica a una fila de células como se muestra a continuación. Las celdas que incluyen 0% y 100% normalmente están ocultas, porque están justo ahí para dar el contexto denominado "ScanProgress" (Alcance).

Scan progress

En el código que estoy bucle a través de una mesa haciendo algunas cosas.

For intRow = 1 To shData.Range("tblData").Rows.Count 

    shData.Range("ScanProgress").Value = intRow/shData.Range("tblData").Rows.Count 
    DoEvents 

    ' Other processing 

Next intRow 

Código mínimo, se ve decente.

+5

El problema principal que veo con este enfoque es que a menudo apago las actualizaciones de pantalla y los cálculos cuando estoy haciendo operaciones grandes que hacen que una barra de progreso sea útil. – VoteCoffee

2

Hola versión modificada de otra publicación por Marecki. Tiene 4 estilos

1. dots .... 
2 10 to 1 count down 
3. progress bar (default) 
4. just percentage. 

Antes de preguntar por qué no editar ese mensaje es que hice y que fue rechazado se le dijo a publicar una nueva respuesta.

Sub ShowProgress() 

    Const x As Long = 150000 
    Dim i&, PB$ 

    For i = 1 To x 
    DoEvents 
    UpdateProgress i, x 
    Next i 

    Application.StatusBar = "" 
End Sub 'ShowProgress 

Sub UpdateProgress(icurr As Long, imax As Long, Optional istyle As Integer = 3) 
    Dim PB$ 
    PB = Format(icurr/imax, "00 %") 
    If istyle = 1 Then ' text dots >>.... <<' 
     Application.StatusBar = "Progress: " & PB & " >>" & String(Val(PB), Chr(183)) & String(100 - Val(PB), Chr(32)) & "<<" 
    ElseIf istyle = 2 Then ' 10 to 1 count down (eight balls style) 
     Application.StatusBar = "Progress: " & PB & " " & ChrW$(10111 - Val(PB)/11) 
    ElseIf istyle = 3 Then ' solid progres bar (default) 
     Application.StatusBar = "Progress: " & PB & " " & String(100 - Val(PB), ChrW$(9608)) 
    Else ' just 00 % 
     Application.StatusBar = "Progress: " & PB 
    End If 
End Sub 
2

Sobre el control progressbar en un formulario de usuario, no se mostrará ningún progreso si no se utiliza el evento repaint. Debe codificar este evento dentro del bucle (y obviamente incrementar el valor progressbar).

Ejemplo de uso:

userFormName.repaint 
0

Solución Publicado por @eykanal puede no ser la mejor en caso de tener gran cantidad de datos a tratar como la habilitación de la barra de estado ralentizaría la ejecución de código.

El siguiente enlace explica una buena forma de crear una barra de progreso.Funciona bien con el volumen de datos a alta (~ registros 250K +):

http://www.excel-easy.com/vba/examples/progress-indicator.html