运行代码

时间:2018-01-04 07:06:35

标签: excel vba performance email-attachments hang

我在这里寻找适用的方法......

  

如何将正在运行的VBA过程发送到后台,以防止工作簿挂起,直到VBA语句运行完毕。

运行VBA程序时挂起......

指出Document.PrintOut内置过程具有Background参数,该参数在Microsoft Word打印文档时继续使用宏。

Excel 挂起,同时运行以下剪辑代码的.Send程序

Dim iMsg As Object
Dim iConf As Object

Set iMsg = CreateObject("CDO.Message")
Set iConf = CreateObject("CDO.Configuration")

With iMsg
    Set .Configuration = iConf
    .To = strTo
    .ReplyTo = "Email Address"
    .From = """Sender Name (Email Address)"" <EmailAddress>"
    .Subject = strSubject
    .TextBody = strBody
    .AddAttachment ThisWorkbook.Path & "\Temp\" & ThisWorkbook.Name
    .Send
End With

Excel 挂起,而For Next循环在以下代码中:

Sub PrintIt()

Dim objWord As Word.Application
Dim objDocTotal As Word.Document
Dim objDoc As Word.Document
Dim i As Integer
Dim strOutfile As String
Dim rg As Word.Range

    ActiveSheet.OLEObjects("SalaryPaycheck").Activate
    Set objWord = GetObject(, "Word.Application")
    objWord.Visible = False
    Set objDoc = objWord.ActiveDocument
    Set objDocTotal = Documents.Add
    objWord.Application.DisplayAlerts = wdAlertsNone
    objWord.Application.ScreenUpdating = False

    For i = worksheetfunction.Min(range("Table1[Column1]") To _
        worksheetfunction.Max(range("Table1[Column1]")

        Range("Key").Value = i

        With objDoc
            .Fields.Update
            .Content.Copy
        End With

        Set rg = objDocTotal.Content
        With rg
            .Collapse Direction:=wdCollapseEnd
            If i > 1 Then .InsertBreak wdPageBreak
            .PasteAndFormat wdFormatOriginalFormatting
        End With
    Next i


    strOutfile = "<Path>\Salary.pdf"

    objDocTotal.ExportAsFixedFormat outputfileName:= _
                                    strOutfile, exportformat:=wdExportFormatPDF, _
                                    openafterexport:=False, optimizefor:=wdExportOptimizeForPrint, Range:= _
                                    wdExportAllDocument, From:=1, To:=1, Item:=wdExportDocumentContent



    objDocTotal.Close False
    objWord.Quit
    Set objDoc = Nothing
    Set objWord = Nothing

End Sub

与上述情况一样,CPU利用率的平均值大约低于40%!

我们从Excel 2007知道支持多线程(support.microsoft.

  

为什么Excel在代码运行时运行某些代码(如上所示)时会挂起,直到它们已终止或结束?

     

如何阻止上面悬挂的工作簿与MS-Word中Background过程的PrintOut参数能力相同?

>

问候。

1 个答案:

答案 0 :(得分:3)

让我总结一下你的问题,尽量让事情尽可能清楚。

  

由于Excel启用了多线程处理,为什么我不能在多个线程上运行我的VBA代码?

因为VBA不支持多线程。所有VBA代码都在一个线程(主线程)上运行。

  

好的,我明白了。现在,由于Excel本身是多线程的,为什么在VBA代码运行时它会冻结?

好吧,VBA代码在主线程上运行。主线程还用于显示Excel GUI 并执行其他操作。现在,当你的VBA代码运行时,它会阻塞主线程,因此冻结。阅读这篇文章:Multithreaded Recalculation in Excel了解更多关于在多个线程上运行的内容:

再次,只要您的VBA代码需要一些时间来处理运行,工作簿将 始终 挂起。您可以通过编写简单的代码来测试它:

RecyclerView

..并观察Excel冻结,直到循环结束。

  

那么,我怎样才能防止工作簿冻结?有没有办法实现这个目标?

嗯,你提出了两个案例:

  1. For i = 1 To 100000 Debug.Print (i) Next 循环

    您可以通过在循环内添加DoEvents来解决此问题。 For做的是它 产生代码的执行以允许处理其他代码 消息。所以,以前的代码看起来像 以下内容:

    DoEvents

    但是,允许用户在代码运行时更改工作簿并不是一个好习惯。有时我会使用For i = 1 To 100000 Debug.Print (i) DoEvents Next (例如,在显示用户表单时),但我确保在我的代码运行时,用户无权访问代码使用的工作表

  2. DoEvents的{​​{1}}方法:

    我相信这会在后台运行,如果正确配置所有内容,则不应阻止该线程。查看this question

  3. 希望有所帮助。