强制Excel VBA中的屏幕更新

我的Excel工具执行一个长时间的任务,我试图通过在状态栏或工作表中的某个单元格中提供进度报告来对用户友好,如下所示。 但屏幕不刷新,或停止刷新某些点(如33%)。 任务最终完成,但进度条是无用的。

我能做些什么来强制屏幕更新?

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 

我正在使用Excel 2003。

在循环中添加一个DoEvents函数,见下文。

您可能还需要确保状态栏对用户可见,并在代码完成时将其重置。

 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 

工作表中的文本框在更改文本或格式时有时不会更新,甚至DoEvent命令也无济于事。

由于在Excel中没有命令以刷新用户表单的方式刷新工作表,所以有必要使用技巧来强制Excel更新屏幕。

以下命令似乎可以做到这一点:

 - ActiveSheet.Calculate - ActiveWindow.SmallScroll - Application.WindowState = Application.WindowState 

在循环中调用DoEvents

这会影响性能,所以你可能只想在每次迭代中调用它。
但是,如果你只有30,那不是一个问题。

特别是,如果您正在处理用户窗体 ,则可以尝试重新绘制方法。 如果您在表单中使用事件触发器,则可能会遇到DoEvents问题。 例如,一个函数运行时按下的任何按键都将由DoEvents发送。键盘input将在屏幕更新之前被处理,所以如果你通过按住键盘上的一个箭头键来改变电子表格上的单元格,在主函数完成之前,单元格更改事件将保持发射状态。

用户窗体在某些情况下不会被刷新,因为DoEvents会触发事件; 但是,重新绘制将更新用户窗体,即使在上一个事件之后紧接着另一个事件时,用户也将在屏幕上看到更改。

在UserForm代码中,它就像下面这样简单:

 Me.Repaint 

这不是直接回答你的问题,而只是提供一个替代scheme。 我发现在很多很长的Excel计算中,大部分时间都是在屏幕上显示Excel更新值。 如果是这种情况,你可以在你的sub的前面插入下面的代码:

 Application.ScreenUpdating = False Application.EnableEvents = False 

并把这作为结束

 Application.ScreenUpdating = True Application.EnableEvents = True 

我发现,这通常会加快我所处理的任何代码,所以不得不提醒用户进度是不必要的。 这只是一个想法,你的尝试,其有效性是相当依赖于你的工作表和计算。

在你正在更新UI的行之前写DoEvents ,它应该工作。