Search code examples
vbaoutlook

VBA user form dies


I have a macro to process my inbox which has 7000 emails (I know, I know) and it takes a while. Naturally, I made a user form to show the progress by settling a label with remaining email count. During execution however, I noticed that the form would stop updating at random time, probably as outlook goes into non responsive due to the macro execution. Yesterday I accidentally dragged the now not-updating form aside which revealed another instance of the form beneath it, and that one is being updated correctly!

What is the mechanism behind this? My macro only created one instance of the form.

Edits: The code is to delete emails with the same subject as the selected email. It was like the following. I added the commented out lines (pb.hide and pb.show) which somewhat solved the problem, although the flicker from hide/show is visually noticeable.

j = myitems.Count \ 20
l = 0
For i = myitems.Count To 1 Step -1
    If l < j Then
        l = l + 1
    Else
        l = 0
        'pb.Hide
         pb.Caption = "Emails to be processed: " & i
        'pb.Show
    End If

    If TypeOf myitems(i) Is Outlook.MailItem Then
        If myitems(i).ConversationID = selectedConversationID Then
            myitems(i).Move deletedItemsFolder
        ElseIf myitems(i).subject = selectedSubject Then
            myitems(i).Move deletedItemsFolder
        End If
    End If
Next i

I have since switched to the Restrict method to get emails with same subject (as well as the GetConversation mehod) which takes seconds so the form is useless now. But they are not foolproof. There are times the selected email itself is not returned. Anyway, no biggie.


Solution

  • VBA is a single-threaded environment not designed for running secondary threads. If you consider creating a COM add-in you could use a low-level code such as Extended MAPI (or any other third-party wrappers around that api such as Redemption) which allows running secondary threads and deal with a store. So, you could move your loop on a secondary thread releasing the UI one (the main thread). Also it makes sense to consider using proper OOM methods and properties that can help to speed up the process of searching for specific items in Outlook. For example, you may consider using the Find/FindNext or Restrict methods of the Items class. They allow getting only items that correspond to the search criteria. Read more about these methods in the following articles:

    The AdvancedSearch method of the Application class can be helpful as well. The key benefits of using the AdvancedSearch method in Outlook are:

    • The search is performed in another thread. You don’t need to run another thread manually since the AdvancedSearch method runs it automatically in the background.
    • Possibility to search for any item types: mail, appointment, calendar, notes etc. in any location, i.e. beyond the scope of a certain folder. The Restrict and Find/FindNext methods can be applied to a particular Items collection (see the Items property of the Folder class in Outlook).
    • Full support for DASL queries (custom properties can be used for searching too). To improve the search performance, Instant Search keywords can be used if Instant Search is enabled for the store (see the IsInstantSearchEnabled property of the Store class).
    • You can stop the search process at any moment using the Stop method of the Search class.