logo di Marco Braglia

Barra di avanzamento per le macro VBA in Excel

MACRO VBA
8 minuti di lettura

Bentrovato sul mio blog, io sono Marco in arte Macro Braglia e, se non mi conosci, sono un esperto di Excel e di automazione con le macro.

Quante volte ti sei chiesto a che punto è la macro che sta lavorando per te e sta “tenendo in ostaggio” il tuo Excel???

Dare un riscontro visivo dell’avanzamento di una procedura è un punto molto importante della User Experience nell’utilizzo di qualsiasi software….e le nostre macro VBA non possono certo essere da meno!

Con la barra di avanzamento (aka: Progress Bar) che imparerai a costruire in questo articolo potrai aggiungere un tocco di professionalità ai tuoi file Excel automatizzati:

barra avanzamento Excel

Ho creato questa barra di avanzamento più di dieci anni fa, quando per la prima volta ne ho avuto bisogno sul lavoro, prendendo spunto da un esempio in inglese trovato sul web che purtroppo non riesco a ritrovare per poterlo linkare e attribuirgli i giusti meriti. Da allora, l’ho conservata con cura e usata in tantissimi progetti professionali e personali.

Gli step necessari per costruire la barra di avanzamento in Excel vba sono i seguenti: 1. Creare la UserForm e aggiustarla graficamente secondo i propri gusti 2. Inserire il codice VBA della UserForm per fare la configurazione iniziale della barra di avanzamento e aggiornarne lo stato mentre la macro procede 3. Invocare la barra di avanzamento e aggiornarla

TL;DR

Puoi scaricare il file completo con la progress bar e un esempio di utilizzo direttamente qui.

Creare la UserForm

Nel menu Sviluppo del nostro Excel, clicca su Inserisci -> UserForm:

inserire una userform

Ridimensiona a piacere la UserForm, rinominala e cambia il titolo (Caption) e, importantissimo, cambia la proprietà ShowModal in False:

ridimensione e rinonima la userform proprietà userform

Aggiungi un’etichetta e rinominala lblStatus:

aggiunta label

Aggiungi un’etichetta e rinominala ProgressBarBG, rappresenterà lo sfondo della nostra barra di avanzamento. Cambia la proprietà BackColor con un colore a scelta (in questo caso bianco), elimina la caption e annotati il valore della proprietà Width:

sfondo progressbar

Copia l’etichetta bianca appena creata, incollala sotto, cambia il nome in ProgressBar, cambia il colore con uno a piacere (in questo caso verde) e spostala esattamente sovrapposta a quella bianca creata in precedenza.

copia label label progress bar

Copia l’etichetta appena creata e incollala sotto. Cambia il nome in lblPercent. Imposta la proprietà BackStyle al valore “0 - fmBackStyleTransparent”. Cambia la caption scrivendo “0%”. Aggiusta le proprietà Height e Top in modo che il testo appaia centrato verticalmente all’interno della barra verde.

percentuale di avanzamento

Aggiungi un’etichetta sotto la barra e cambia Name e Caption in lblRunTime:

label run time

Ripeti per l’ultima etichetta con Name e Title lblRemainingTime:

label remaining time

Aggiungi un pulsante e cambia il Name in CancelButton e la Caption in Annulla:

button annulla

Inserire il codice nella UserForm

Fai clic destro sul nome della UserForm e seleziona Visualizza Codice:

visualizza codice

Nella finestra che si apre incolla il seguente codice:

inserisci codice userform
Option Explicit
 
Dim Cancelled As Boolean, showTime As Boolean, showTimeLeft As Boolean
Dim startTime As Long
Dim BarMin As Long, BarMax As Long, BarVal As Long
 
Private Declare PtrSafe Function GetTickCount Lib "Kernel32" () As Long
 
'Title will be the title of the dialogue.
'Status will be the label above the progress bar, and can be changed with SetStatus.
'Min is the progress bar minimum value, only set by calling configure.
'Max is the progress bar maximum value, only set by calling configure.
'CancelButtonText is the caption of the cancel button. If set to vbNullString, it is hidden.
'optShowTimeElapsed controls whether the progress bar computes and displays the time elapsed.
'optShowTimeRemaining controls whether the progress bar estimates and displays the time remaining.
'calling Configure sets the current value equal to Min.
'calling Configure resets the current run time.
Public Sub Configure(ByVal title As String, ByVal status As String, _
                     ByVal Min As Long, ByVal Max As Long, _
                     Optional ByVal CancelButtonText As String = "Cancel", _
                     Optional ByVal optShowTimeElapsed As Boolean = True, _
                     Optional ByVal optShowTimeRemaining As Boolean = True)
    Me.Caption = title
    lblStatus.Caption = status
    BarMin = Min
    BarMax = Max
    BarVal = Min
    CancelButton.Visible = Not CancelButtonText = vbNullString
    CancelButton.Caption = CancelButtonText
    startTime = GetTickCount
    showTime = optShowTimeElapsed
    showTimeLeft = optShowTimeRemaining
    lblRunTime.Caption = ""
    lblRemainingTime.Caption = ""
    Cancelled = False
End Sub
 
'Set the label text above the status bar
Public Sub SetStatus(ByVal status As String)
    lblStatus.Caption = status
    DoEvents
End Sub
 
'Set the value of the status bar, a long which is snapped to a value between Min and Max
Public Sub SetValue(ByVal value As Long)
    If value < BarMin Then value = BarMin
    If value > BarMax Then value = BarMax
    Dim progress As Double, runTime As Long
    BarVal = value
    progress = (BarVal - BarMin) / (BarMax - BarMin)
    ProgressBar.Width = 292 * progress
    lblPercent = Int(progress * 100) & "%"
    runTime = GetRunTime()
    If showTime Then lblRunTime.Caption = "Tempo Trascorso: " & GetRunTimeString(runTime, True)
    If showTimeLeft And progress > 0 Then _
        lblRemainingTime.Caption = "Tempo rimanente (stima): " & GetRunTimeString(runTime * (1 - progress) / progress, False)
    DoEvents
End Sub
 
'Get the time (in milliseconds) since the progress bar "Configure" routine was last called
Public Function GetRunTime() As Long
    GetRunTime = GetTickCount - startTime
End Function
 
'Get the time (in hours, minutes, seconds) since "Configure" was last called
Public Function GetFormattedRunTime() As String
    GetFormattedRunTime = GetRunTimeString(GetTickCount - startTime)
End Function
 
'Formats a time in milliseconds as hours, minutes, seconds.milliseconds
'Milliseconds are excluded if showMsecs is set to false
Private Function GetRunTimeString(ByVal runTime As Long, Optional ByVal showMsecs As Boolean = True) As String
    Dim msecs&, hrs&, mins&, secs#
    msecs = runTime
    hrs = Int(msecs / 3600000)
    mins = Int(msecs / 60000) - 60 * hrs
    secs = msecs / 1000 - 60 * (mins + 60 * hrs)
    GetRunTimeString = IIf(hrs > 0, hrs & " ore ", "") _
                     & IIf(mins > 0, mins & " minuti ", "") _
                     & IIf(secs > 0, IIf(showMsecs, secs, Int(secs + 0.5)) & " secondi", "")
End Function
 
'Returns the current value of the progress bar
Public Function GetValue() As Long
    GetValue = BarVal
End Function
 
'Returns whether or not the cancel button has been pressed.
'The ProgressDialogue must be polled regularily to detect whether cancel was pressed.
Public Function cancelIsPressed() As Boolean
    cancelIsPressed = Cancelled
End Function
 
'Recalls that cancel was pressed so that they calling routine can be notified next time it asks.
Private Sub CancelButton_Click()
    Cancelled = True
    lblStatus.Caption = "Cancelled By User. Please Wait."
End Sub
 
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    Cancelled = True
    lblStatus.Caption = "Cancelled By User. Please Wait."
End Sub

Nella funzione SetValue, cambia il numero con la Width impostata per le etichette ProgressBarBG e ProgressBar nei punti precedenti. Questo ti servirà per fare in modo che la barra di avanzamento si estenda con le proporzioni giuste sulle label effettive che hai inserito in precedenza nella UserForm.

cambiare width nel vba

Invocare la barra di avanzamento e utilizzarla

Per poter utilizzare la barra di avanzamento in Excel appena creata, è necessario invocarla all’interno della tua propria macro VBA. In questo esempio andremo ad utilizzare un codice che non fa nulla di pratico ma mostra la barra di avanzamento in un ciclo for da -10.000 a +10.000.

I passaggi per utilizzare la barra di avanzamento sono:

  1. Inizializzare un nuovo ProgressDialogue
  2. Fare la configurazione iniziale impostando Title, Status, Min e Max
  3. Mostrare il ProgressDialogue
  4. Per ogni iterazione della tua macro, aggiornare il Value e lo Status del ProgressDialogue in modo che la barra possa “avanzare”
  5. Nascondere il ProgressDialogue al termine della macro

Clicca su Inserisci->Modulo

inserisci modulo

Aggiungi un modulo, cambia il nome in Test e al suo interno incolla il seguente codice:

codice vba modulo Test
Sub Test()
    Dim i As Long
    Dim diag As New ProgressDialogue
    diag.Configure "Test Avanzamento", "Sto avanzando...", -10000, 10000
    diag.Show
    For i = -10000 To 10000
        diag.SetValue i
        diag.SetStatus "Sto avanzando... " & i
        On Error Resume Next
        If diag.cancelIsPressed Then Exit For
        On Error GoTo 0
    Next i
    diag.Hide
End Sub

Nel foglio Excel (fuori quindi dall’editor VBA) clicca su Sviluppo->Inserisci->Controlli Modulo – Pulsante:

inserisci pulsante sul foglio

Disegna la forma sul foglio e, nel finestra pop up che si apre, seleziona la macro Test creata in precedenza:

selezione macro per pulsante

Fai clic destro sul pulsante -> Modifica Testo per modificare il testo visualizzato dentro al pulsante:

modifica testo pulsante

E ora non ti resta che cliccare sul pulsante di TEST e goderti la tua nuova barra di avanzamento in Excel:

barra avanzamento Excel

#ExcelHaSempreRagione