为什么UserForm在VBA Excel中的运行时“无响应”?

时间:2012-11-28 13:51:24

标签: vba excel-vba userform excel

我是VBA Excel的新手,我只知道这个报告格式化任务所需的东西。

我差不多完成了我的任务,但是当我运行程序并开始进度时,尽管它成功运行,但GUI没有响应一分钟。我在这里分享我的代码,它有什么问题吗?你能建议我做最好的练习吗?我不希望它冻结,因为它对我的经理来说看起来很糟糕。

只是为了说清楚,“没有回应”我的意思是它冻结在屏幕上并在它的窗框上说“没有回应”,当我点击它时,它会给出这样的信息:

enter image description here

* ps:我获得记录的工作表有20997行和7列,我在同一文件大小和20997行23列上的另一张纸上做了一些记录。我的GUI非常简单,它只有一个启动进度的CommandButton。

我该如何解决这个问题?

4 个答案:

答案 0 :(得分:19)

您可以通过添加

来防止冻结Excel窗口
DoEvents

在你的循环中。

答案 1 :(得分:4)

这是因为您的程序非常繁忙。例如,您的Sub TheLoop()正在访问一个单元格的20995 x 16倍,以便在其上写入一个字符串。 VBA与Excel的交互很慢。

您可以采取一些措施来加快手术速度。

1.在运行程序之前,禁用事件处理程序,屏幕更新和计算。在该过程结束时,再次恢复设置。

   'Disable'
   Application.EnableEvents = False
   Application.ScreenUpdating = False
   Application.Calculation = xlCalculationManual

   '......  Code'

   'Enable'
   Application.EnableEvents = True
   Application.ScreenUpdating = True
   Application.Calculation = xlCalculationAutomatic

2.您可以优化Sub TheLoop。不要立即在单元格上写入,而是在数组中写入值。在数组满了值后,将数组的值分配给您需要的范围。  例如:

Dim ResultValues() As String
Dim j As Long

ReDim ResultValues(2 To 20997, 1 To 3)

For j = 2 To 20997
    ResultValues(j, 1) = "New Defect"
    ResultValues(j, 2) = "3"
    ResultValues(j, 3) = "2"
Next j

With ThisWorkbook.Worksheets("myWorksheet")
    .Range(.Cells(2, 3), .Cells(20997, 5)) = ResultValues
End With

修改

鉴于您修改的列之间的列只是文本或空单元格,您可以:

  1. 将整个范围读入数组。
  2. 然后以与当前修改单元格相同的方式修改数组。
  3. 完成修改后,再将整个矩阵转储到范围内。'
  4. 例如:

    Sub TheLoop()
    Dim arrRangeValues() as Variant
    Dim j as Long
    
    arrRangeValues= Range("A2:V20997").Value2
    
    For j = 2 To 20997
        arrRangeValues(j, 1) = "Defect" 'Cells(row_index , column_index)'
        arrRangeValues(j, 3) = "New Defect"
        arrRangeValues(j, 4) = "3" ' this one also might be empty'
        arrRangeValues(j, 5) = "2" ' this one also might be empty'
    
        arrRangeValues(j, 7) = "Name Surname"
        arrRangeValues(j, 8) = arrRangeValues(j, 7)
        arrRangeValues(j, 16) = arrRangeValues(j, 7)
        ...
        arrRangeValues(j, 10) = " http://SERVER_NAME:8888/PROJECT_NAME/ "
    Next j
    
    Range("A2:V20997").Value2 = arrRangeValues
    End Sub
    

答案 2 :(得分:0)

好吧,我相信我找到了最好的解决方案。 (a):)

我没有在TheLoop子程序中使用for循环,而是删除了循环并更改了它,如下所示。当我将它与我的第一个代码事件进行比较时,这会让它变得非常快,尽管我没有禁用事件属性,现在它并没有冻结。

Sub TheLoop()

    Cells(2, 1).Resize(20996) = "Defect"
    Cells(2, 3).Resize(20996) = "New Defect"
    Cells(2, 4).Resize(20996) = "3"
    Cells(2, 5).Resize(20996) = "2"
    Cells(2, 7).Resize(20996) = "Name Surname"
    Cells(2, 8).Resize(20996) = "Name Surname"
    Cells(2, 9).Resize(20996) = "FALSE"


    Cells(2, 10).Resize(20996) = " http://SERVER_NAME:8888/PROJECT_NAME/ "


    Cells(2, 12).Resize(20996) = "Software Quality"
    Cells(2, 13).Resize(20996) = "Unsigned"
    Cells(2, 14).Resize(20996) = "Software Quality"
    Cells(2, 15).Resize(20996) = "1"
    Cells(2, 16).Resize(20996) = "Name Surname"
    Cells(2, 18).Resize(20996) = "Software Quality"
    Cells(2, 20).Resize(20996) = "Development"
    Cells(2, 22).Resize(20996) = " TYPE YOUR MODULE'S NAME TO HERE"

End Sub

答案 3 :(得分:0)

我尝试过 Application.ScreenUpdating、Application.EnableEvents、Application.Calculation、DoEvents 和 Application.Wait (Now + TimeValue("0:00:10")),不幸的是,最后的选项无法解决这个问题问题,如果程序说我“无响应”

,请查看 Microsoft 网页说我
  1. 出于安全原因和
  2. 因为太重或太复杂
  3. 因为程序不会向用户发送任何反馈信息。

在我的例子中,我尝试向用户展示和 MsgBox 最终为 Win10 操作系统和客户提供反馈,但是太无聊以至于用户点击是,是,是,是的,好的,好的,好的,好的,并在其他论坛上查看有关 MsgBox 的 VBA(自动关闭),他们建议我使用代码 CreateObject("WScript.Shell").PopUp "Please Wait", 1 和 tada !!我将停止看到“未响应消息”,如果用户不按任何单击或按钮来禁用消息,请不要担心程序会在消息关闭后 1 秒后执行,在我的情况下,这解决了我的问题很多,希望能帮到你,祝你好运。