如何防止macros冻结/变成白色的Excel窗口?

所以在工作中,我正在为Excel中的macros/ UserForm Excel中工作。 它工作得很好(我认为),并且完成它需要做的事情,并在1分钟之内运行,通过约70,000个单元并组织它们。 现在我想知道是否有办法减慢速度,以便Excel在运行时不会进入“Not Responding”模式。 这样做会更好,因此需要使用macros的人在冻结时不会被吓倒。 如果在VBA中有一个解决scheme,那么最好的办法就是不用担心这个问题。

关于macros

数据是需要放在一列中的一堆数字,而且在14(通常是14)列之前用每个数字标记每个数字。 所有大小的引用和表名都需要来自用户窗体,所以我不知道表单的名称或大小提前,这导致在我的循环开始一些奇怪的代码。

此外,如果您看到无论如何使我的代码更高效,将不胜感激!

代码

Private Sub UserForm_Initialize() 'This brings up the data for my dropdown menu to pick a sheet to pull data from For i = 1 To Sheets.Count combo.AddItem Sheets(i).name Next i End Sub Private Sub OK_Click() Unload AutoPivotusrfrm 'Declaring All of my Variables that are pulled from Userform Dim place As Long Dim x1 As Integer x1 = value1.Value Dim x2 As Integer x2 = value2.Value Dim x3 As Integer x3 = value4.Value Dim y1 As Integer y1 = value3.Value Dim copyRange As Variant Dim oldname As String oldsheetname = combo.Text Dim newname As String newname = newsheetname.Text Sheets.Add.name = newsheetname 'Labels for section one Worksheets(CStr(oldsheetname)).Activate copyRange = Range(Cells(x1, x1), Cells(x1 + 1, x3 - 1)).Value Worksheets(CStr(newsheetname)).Activate Range(Cells(x1, x1), Cells(x1 + 1, x3 - 1)).Value = copyRange place = x1 + 2 x1 = place 'Looping through the cells copying data For i = x1 To x2 'This was the only way to copy multiple cells at once other ways it would just error Worksheets(CStr(oldsheetname)).Activate copyRange = Range(Cells(i + 3 - x1, x1 - 2), Cells(i + 3 - x1, x3 - 1)).Value Worksheets(CStr(newsheetname)).Activate For j = x3 To y1 Range(Cells(place, 1), Cells(place, x3 - 1)).Value = copyRange Cells(place, x3) = Sheets(CStr(oldsheetname)).Cells(1, j) Cells(place, x3 + 1) = Sheets(CStr(oldsheetname)).Cells(2, j) Cells(place, x3 + 2) = Sheets(CStr(oldsheetname)).Cells(i + 2, j) place = place + 1 Next j Next i End Sub Private Sub cancel_Click() Unload AutoPivotusrfrm End Sub 

正如注释中提到的@stuartd, DoEvents可能允许用户在macros运行时与Excel交互,并防止Excel无响应。

另一种方法是加速你的代码,以便在用户有理由相信它已经崩溃之前完成。 在这方面,这里有一些build议:

  1. closures屏幕更新:对于Excel渲染屏幕是很多工作。 您可以通过将Application.ScreenUpdating = False添加到代码的开头,并将Application.ScreenUpdating = True到最后,来释放这些资源以处理您需要完成的工作。

  2. closures计算:如果有很多公式正在运行,这可能会减慢将值放入工作簿时发生的情况,因为它需要重新计算。 我的首选方法是存储当前的计算设置,closures计算,然后在最后恢复原始设置。

 Dim Calc_Setting as Long Calc_Setting = Application.Calculation Application.Calculation = xlCalculationManual 'Your code here Application.Calculation = Calc_Setting 
  1. 使用工作表variables:您继续按名称访问您的工作表。 对于重复访问,将其存储在variables中应该更快。 与此同时,不要使用ActivateSelect 。 完全引用您对Cells调用,以便访问正确的工作表。

 Dim oldsheet as Worksheet, newsheet as Worksheet Set oldsheet = Worksheets(CStr(oldsheetname)) Set newsheet = Worksheets(CStr(newsheetname)) oldsheet.Cells(place, x3) = ... 
  1. 使用变体数组:这应该加快你的代码最多,但也有一个警告 。 Excel和VBA在交互时很慢。 在你的内部循环中,VBA访问Excel 7次。 通过将这些相互作用拉出循环,我们可以实现一个严重的性能提升。 问题是读取/写入数组到Excel范围仍然受到2003年的大小限制(65536行,…)。 如果你希望有更多的数据,那么你需要做一些体操来使其工作。

 Dim inVal as Variant, Output as Variant inVal = Range(oldsheet.Cells(1,x1-2),oldsheet.Cells(x2+3-x1,y)).Value redim output(1 to (x2-x1) * (y-x3) + 2, 1 to x3+2) 'These numbers are not tested, you should test. 'Loops to fill output. This will need to be 1 entry at a time. newsheet.Cells(x1,x1).Resize(Ubound(output,1), Ubound(output,2)).Value