2010-10-05 3 views
5

Я использую DoEvents для принудительного обновления индикатора прогресса в строке состояния (или в некоторой ячейке на листе), как в приведенном ниже примере кода. Но экран не обновляется, или перестает освежать в какой-то момент. Задача в конечном итоге завершается, но индикатор прогресса бесполезен.DoEvents не делает событий ... Почему?

Почему не будет DoEvents «делать события»? Что еще я могу сделать, чтобы принудительно обновить экран?

Редактировать: Я использую Excel 2003 для Windows XP.

Это последующий до earlier question; спасибо Robert Mearns за его ответ и пример кода ниже.

Sub ProgressMeter() 

Dim booStatusBarState As Boolean 
Dim iMax As Integer 
Dim i As Integer 

iMax = 100 

    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 
+5

Вы пробовали без 'Application.ScreenUpdating = false'? –

+0

Любопытный ... он работает нормально (добавляет внутреннюю петлю на какое-то время) на моей машине ... –

+0

Пожалуйста, опубликуйте версии Excel & OS –

ответ

9

Я нашел DoEvents не всегда полностью надежным. Я бы предложил попробовать две разные вещи.

Сначала попробуйте поместить вызов DoEvents сразу после обновления строки состояния (то есть перед вашей линией Some code ....).

Если это не сработает, в некоторых случаях я обнаружил, что использование Sleep API является более надежным способом получения процессорного времени. Обычно это первое, что я пытаюсь сделать, если DoEvents работает не так, как хотелось бы. Вам нужно добавить следующую строку в верхней части модуля (за пределами вашей функции):

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

Затем добавьте эту строку вместо или в дополнение к, DoEvents:

Sleep 1 'This will pause execution of your program for 1 ms 

Возможно, вы попытаетесь увеличить время паузы в программе, используя sleep, если 1 мс не работает.

1

Я обнаружил, что вызов DoEvents перед обновлением строки состояния, а не после, дает более предсказуемые/желаемые результаты.

фрагмент кода из выше будет:

fractionDone = CDbl(i)/CDbl(iMax) 
    DoEvents 
    Application.StatusBar = Format(fractionDone, "0%") & " done..."