0

Here I'm looking for an applicable approach...

How can send the running VBA procedures to background for prevent workbook hangs until the VBA statements running are finished.

Hangs when running a VBA procedure...

Point that the Document.PrintOut built-in procedure has Background argument which have the macro continue while Microsoft Word prints the document.

The Excel Hangs while running .Send procedure of below snip code

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 Hangs while For Next loop in below code:

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

As in above cases the average of CPU Utilization is approximately lower than 40%!

And we know from Excel 2007 the multi-threaded is supported (support.microsoft.)

Why Excel hangs when running some codes (as exampled above) while the codes running, up to they have terminated or end?

How can prevent Workbooks hanging in above same as the Background's argument ability for PrintOut procedure in MS-Word which said at top of here?

Regards.

Community
  • 1
  • 1
Tuberose
  • 434
  • 6
  • 24
  • My question has compared between running; when the `Background` argument of `PrintOut` procedure is enabled and running other procedures. Here we not focused on Multi threaded approach. Please read the question with more precision. Regards. – Tuberose Jan 04 '18 at 07:32
  • 1
    I'm not sure I understand your comment. VBA is not multi-threaded enabled, so you can't choose to run part of your code in a separate thread. **Some** VBA functions (such as printing a Word document) have the option to be sent to a background process but that is not something that is able to be done with **all** VBA functions. Check MSDN for each function that you wish to use to see whether any sort of background processing is possible. – YowE3K Jan 04 '18 at 07:42
  • @YowE3k, Thank you so much. You reached my mean. **About Multi-threaded:** The Excel from 2007, is supporting multi-threaded. And **Excel workbook** is hanged, when the procedures running in above (in the question) exampled cases. How can we send to background the process of our desired procedures? If it is an applicable approach. – Tuberose Jan 04 '18 at 07:50
  • @Tuberose OK...i've retracted the duplicate-flag. But as you write in your question, you assume that **VBA** provides support for multi-threading. However, this is clearly denied in the link you posted. – MatSnow Jan 04 '18 at 07:50
  • 2
    Your code shouldn't hang - but the code can't proceed to the next VBA statement until the current VBA statement (such as `iMsg.Send`) is finished processing, because VBA is not multi-threaded, and Excel itself can't do any processing while the VBA code is running. I think you are confusing Excel being multi-threaded with VBA being multi-threaded. – YowE3K Jan 04 '18 at 07:53
  • Regard you **MathSnow**. Above I said "from Excel 2007 the multi-threaded is supported". My mean is multi-threaded is supported in Excel. – Tuberose Jan 04 '18 at 07:53
  • 2
    @Tuberose Enabling multi-threaded processing for Excel is one thing, and using multi-threading in VBA _(which is **not** supported)_ is a totally different thing. As MatSnow told you above, the link in your question states this very clearly: _"Additionally: this setting is not available in the Object Model for use in VBA. "_. – 41686d6564 stands w. Palestine Jan 04 '18 at 07:54
  • @AhmedAbdelhameed, Right. My mean is why when the vba statement (such as `iMsg.Send`) is running, the Excel Workbook have hanged while the Excel is supported multi-threaded. – Tuberose Jan 04 '18 at 07:57
  • Read YowE3K's comment above. Quote: _"..because VBA is not multi-threaded, and Excel itself can't do any processing while the VBA code is running."_. – 41686d6564 stands w. Palestine Jan 04 '18 at 07:58
  • @YowE3k, The Workbook hangs, while my code is running, until the statment processing finished (such as `IMsg.Send` or the `For Next` loop) – Tuberose Jan 04 '18 at 07:59
  • @AhmedAbdelhameed, The Excel is multi-threaded. Why the Excels Workbook hangs while the VBA code is running? The concept is Excel is multi-threaded. Excel can run with other CPU core. I want send running my procedure to background same as act of MS-Word `PrintOut` function. – Tuberose Jan 04 '18 at 08:02
  • 1
    If your VBA code is running while Excel is doing things (e.g. by adding `DoEvents` statements to your code) you run the risk of changes being made to the Excel workbook that your code is not expecting. It is a bad idea. But your VBA code cannot yield control **within** a single statement, only between statements, because VBA is not multi-thread enabled. – YowE3K Jan 04 '18 at 08:23

1 Answers1

3

Let me summarize your questions and try to make things as clear as possible to you..

Since multi-threaded processing is enabled for Excel, why can't I run my VBA code on multiple threads?

Because VBA doesn't support multi-threading. All VBA code runs on one thread (the main thread).

Okay, I get that. Now since Excel itself is multi-threaded, why does it freeze while the VBA code is running?

Well, VBA code runs on the main thread. The main thread is also used to display the Excel GUI and do other things. Now, when your VBA code is running, it blocks the main thread, hence the freezing. Read this article: Multithreaded Recalculation in Excel for more about what exactly runs on multiple threads:

So again, The workbook will always hang whenever you have VBA code that's taking some time to process running. You can test that by writing code as simple as:

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

..and watch Excel freezes until the loop finishes.

So, how can I prevent the workbook from freezing? Is there no way to achieve this?

Well, you proposed two cases:

  1. The For loop:

    You might use a workaround for this by adding DoEvents inside the loop. What DoEvents does is that it yields the execution of your code to allow processing other messages. So, the previous code would look something like the following:

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

    However, it's not really a good practice to allow the user to make changes to the workbook while your code is running. Sometimes I do use DoEvents (e.g., when displaying a userform), but I make sure that while my code is running the user doesn't have access to the sheet being used by the code.

  2. The .Send method of CDO.Message:

    I believe this runs in the background and shouldn't block the thread if configure everything correctly. Check this question.

Hope that helps.

  • Thank you so much. Covered my question entirely. The problem is `.Send` statement which hangs related to the `.Attachments.Add TempFileName` the `TempFileName` file size. When I attaching small files or running `.Send` without attachment, no problems. The `.Send` statement made workbook hanged, depended the `TempFileName` file size which attached. Is it possible running `.Send` in background? – Tuberose Jan 04 '18 at 10:22
  • 1
    @Tuberose It should actually run in the background as I stated in my answer (I just tested that as well). If it blocks then maybe (I'm not sure) it has something to do with your server configurations (did you check the question I linked?). Try with gmail SMTP, if it works fine, then it must be something with your server. You can refer to the code in [this question](https://stackoverflow.com/q/41463936/4934172) for using gmail SMTP. – 41686d6564 stands w. Palestine Jan 04 '18 at 11:31
  • These two questions you linked, are not Attachment container. The `.Send` function hangs until the attachment file have uploaded. If there is no attachments, `.Send` not force Workbook hangs. I suggest you testing `.Send` function with `.AddAttachment TempFileName` for **CDO Mail**. There is no problem when using Mail Server (as Outlook). – Tuberose Jan 04 '18 at 11:36
  • 1
    Running in background = It doesn't matter if you have attachments or not, because uploading the attachment is part of the process that's running in the background. Use the code from the second question with gmail (and add your attachment). If it works, you can start debugging from there. FYI, I just tested that code **with attachments** and it worked without blocking. – 41686d6564 stands w. Palestine Jan 04 '18 at 11:41
  • Thank you so much. As you mentioned me, the code in second question works right in background and my workbook not hangs. Regards. – Tuberose Jan 04 '18 at 11:57
  • Please visit this [related question](https://stackoverflow.com/q/48132209/9075944). My problem not solved and I tried to ask with focus on the problem root. – Tuberose Jan 06 '18 at 21:54