Forcer une mise à jour de l'écran dans Excel VBA
mon outil Excel effectue une longue tâche, et j'essaie d'être gentil avec l'utilisateur en fournissant un rapport d'étape dans la barre d'état, ou dans une cellule de la feuille, comme indiqué ci-dessous. Mais l'écran ne se rafraîchit pas, ou cesse de se rafraîchir à un moment donné (par exemple 33%). La tâche est finalement terminée, mais la barre de progression est inutile.
Que puis-je faire pour forcer une mise à jour d'écran?
For i=1 to imax ' imax is usually 30 or so
fractionDone=cdbl(i)/cdbl(imax)
Application.StatusBar = Format(fractionDone, "0%") & "done..."
' or, alternatively:
' statusRange.value = Format(fractionDone, "0%") & "done..."
' Some code.......
Next i
J'utilise Excel 2003.
6 réponses
Ajouter un DoEvents fonction à l'intérieur de la boucle, voir ci-dessous.
Vous pouvez également vous assurer que la barre D'État est visible à l'utilisateur et la Réinitialiser lorsque votre code est terminé.
Sub ProgressMeter()
Dim booStatusBarState As Boolean
Dim iMax As Integer
Dim i As Integer
iMax = 10000
Application.ScreenUpdating = False
''//Turn off screen updating
booStatusBarState = Application.DisplayStatusBar
''//Get the statusbar display setting
Application.DisplayStatusBar = True
''//Make sure that the statusbar is visible
For i = 1 To iMax ''// imax is usually 30 or so
fractionDone = CDbl(i) / CDbl(iMax)
Application.StatusBar = Format(fractionDone, "0%") & " done..."
''// or, alternatively:
''// statusRange.value = Format(fractionDone, "0%") & " done..."
''// Some code.......
DoEvents
''//Yield Control
Next i
Application.DisplayStatusBar = booStatusBarState
''//Reset Status bar display setting
Application.StatusBar = False
''//Return control of the Status bar to Excel
Application.ScreenUpdating = True
''//Turn on screen updating
End Sub
les zones de texte dans les feuilles de travail ne sont parfois pas mises à jour lorsque leur texte ou formatage est modifié, et même la commande DoEvent n'aide pas.
comme il n'y a pas de commande dans Excel pour rafraîchir une feuille de travail dans la façon dont un utilisateur peut être actualisé, il est nécessaire pour utiliser un truc pour forcer Excel à mettre à jour l'écran.
Les commandes suivantes semblent faire l'affaire:
- ActiveSheet.Calculate
- ActiveWindow.SmallScroll
- Application.WindowState = Application.WindowState
Mettre un appel à DoEvents
dans la boucle.
cela affectera la performance, donc vous pourriez ne l'appeler que sur chaque, disons, dixième itération.
Cependant, si vous n'en avez que 30, ce n'est pas un problème.
Ce n'est pas répondre directement à votre question, mais simplement de fournir une alternative. J'ai trouvé dans les nombreux calculs longs Excel que la plupart du temps d'attente a des valeurs de mise à jour Excel sur l'écran. Si c'est le cas, vous pouvez insérer le code suivant à l'avant de votre sous:
Application.ScreenUpdating = False
Application.EnableEvents = False
et mettez ceci comme la fin
Application.ScreenUpdating = True
Application.EnableEvents = True
j'ai constaté que souvent, cela accélère le code que je travaille tellement que d'avoir à alerter l'utilisateur de la le progrès n'est pas nécessaire. C'est juste une idée à essayer, et son efficacité dépend de votre feuille et de vos calculs.
spécifiquement, si vous avez affaire à un UserForm, vous pouvez essayer l' Repeindre méthode. Vous pourriez rencontrer un problème avec DoEvents si vous utilisez event triggers dans votre forme. Par exemple, toutes les touches enfoncées pendant l'exécution d'une fonction sera envoyé par DoEvents l'entrée du clavier sera traitée avant la mise à jour de l'écran, donc si vous changez des cellules sur une feuille de calcul en maintenant enfoncée l'une des touches fléchées clavier, puis l'événement de changement de cellule va continuer à tirer avant la fin de la fonction principale.
un UserForm ne sera pas rafraîchi dans certains cas, parce que DoEvents va déclencher les événements; cependant,Repeindre mettra à jour le formulaire Utilisateur et l'utilisateur verra les changements à l'écran même si un autre événement suit immédiatement l'événement précédent.
dans le code UserForm, c'est aussi simple que:
Me.Repaint
Écrire DoEvents
juste avant la ligne où vous mettez à jour L'interface utilisateur, cela devrait fonctionner.