+ Reply to Thread
Results 1 to 19 of 19

For Each loop taking long to run

Hybrid View

  1. #1
    Registered User
    Join Date
    02-17-2014
    Location
    Florida
    MS-Off Ver
    Excel 2016
    Posts
    62

    For Each loop taking long to run

    Hello experts.

    I have some code that runs through a few thousand lines of data to look for two conditions and if found copy to a separate spreadsheet to load into a listbox. I'm sure there are many better ways to achieve this which is why I'm reaching out for assistance. I've tried all the usual things to speed it up, but am now at a loss. Currently it takes about 30-40 seconds to complete to even show the userform.

    Specifics:
    * 2 worksheets (CMR's 2018 and CMR Tracking)
    * 26 columns used across
    * a few thousand rows (sheet will be used for entire year)

    What it's looking for:
    If column Y has a date and Z does not (Return the row)
    If column W has a name and Y has no date (Return the row)

    Here's the code - please suggest away!

    Sub OutstandingWOs()
    
    Dim y As Range
    Dim i As Long
    Dim lastColumn As Integer
    Dim lastRowSource As Long
    Dim lastRowDestination As Long
    Dim wsSource As Worksheet
    Dim wsDestination As Worksheet
    
    Set wsSource = Sheets("CMRs " & Year(Now))
    Set wsDestination = Sheets("CMR Tracking")
    
    lastColumn = wsSource.Cells(1, Columns.Count).End(xlToLeft).Column
    lastRowSource = wsSource.Range("F" & Rows.Count).End(xlUp).Row
    lastRowDestination = wsDestination.Range("F" & Rows.Count).End(xlUp).Row + 1
    
    Application.ScreenUpdating = False
    EventState = Application.EnableEvents
    Application.EnableEvents = False
    CalcState = Application.Calculation
    Application.Calculation = xlCalculationManual
    PageBreakState = ActiveSheet.DisplayPageBreaks
    ActiveSheet.DisplayPageBreaks = False
    
    wsDestination.Range("A2:Z" & lastRowDestination).ClearContents
    
    i = 2
    
    For Each y In wsSource.Range("Y2:Y" & lastRowSource)
    
    If Not IsEmpty(y) And y.Offset(0, 1) = "" Or IsEmpty(y) And y.Offset(0, -2) <> "" Then
    
    y.EntireRow.Copy wsDestination.Cells(i, 1)
        
        i = i + 1
        Else
        End If
    Next
    
    Set wsSource = Nothing
    Set wsDestination = Nothing
    
    ActiveSheet.DisplayPageBreaks = PageBreakState
    Application.Calculation = CalcState
    Application.EnableEvents = EventState
    Application.ScreenUpdating = True
    
    End Sub

  2. #2
    Forum Moderator davesexcel's Avatar
    Join Date
    02-19-2006
    Location
    Regina
    MS-Off Ver
    MS 365
    Posts
    13,486

    Re: For Each loop taking long to run

    Have you tried just using the autofilter? It would filter your conditions, then you can copy and paste the entire filtered data.

  3. #3
    Registered User
    Join Date
    02-17-2014
    Location
    Florida
    MS-Off Ver
    Excel 2016
    Posts
    62

    Re: For Each loop taking long to run

    I have not. Great suggestion!

    Do you mean to autofilter manually and then copy with VBA, or is there a VBA solution to perform both?

  4. #4
    Forum Moderator davesexcel's Avatar
    Join Date
    02-19-2006
    Location
    Regina
    MS-Off Ver
    MS 365
    Posts
    13,486

    Re: For Each loop taking long to run

    Quote Originally Posted by Jay S. View Post
    I have not. Great suggestion!

    Do you mean to autofilter manually and then copy with VBA, or is there a VBA solution to perform both?
    You can practice doing it manually, then once you have that perfected, use the macro recorder to get a code, you can then ask for assistance to get the code cleaned up.

  5. #5
    Registered User
    Join Date
    02-17-2014
    Location
    Florida
    MS-Off Ver
    Excel 2016
    Posts
    62

    Re: For Each loop taking long to run

    lol...oh ya! Thanks Dave

  6. #6
    Valued Forum Contributor
    Join Date
    04-01-2015
    Location
    The Netherlands
    MS-Off Ver
    2003/2007/2010/2016/office 365
    Posts
    880

    Re: For Each loop taking long to run

    Can you place an example of the file?
    I do not understand the conditions.

    If Not IsEmpty(y) And y.Offset(0, 1) = "" Or IsEmpty(y) And y.Offset(0, -2) <> "" Then

  7. #7
    Registered User
    Join Date
    02-17-2014
    Location
    Florida
    MS-Off Ver
    Excel 2016
    Posts
    62

    Re: For Each loop taking long to run

    What it's looking for:
    If column Y has a date and Z does not (Return the row)
    If column W has a name and Y has no date (Return the row)

  8. #8
    Valued Forum Contributor
    Join Date
    04-01-2015
    Location
    The Netherlands
    MS-Off Ver
    2003/2007/2010/2016/office 365
    Posts
    880

    Re: For Each loop taking long to run

    Just a guess without a sample file.

    Sub VenA()
      Sheets("CMR Tracking").Cells(1).CurrentRegion.Offset(1).ClearContents
      With Sheets("CMRs " & Year(Now)).Cells(1).CurrentRegion
        .AutoFilter 26, "<>"
        .AutoFilter 23, "<>"
        .Copy Sheets("CMR Tracking").Cells(2, 1)
        .AutoFilter
      End With
    End Sub

  9. #9
    Registered User
    Join Date
    02-17-2014
    Location
    Florida
    MS-Off Ver
    Excel 2016
    Posts
    62

    Re: For Each loop taking long to run

    Sample attached.
    Attached Files Attached Files

  10. #10
    Forum Guru
    Join Date
    08-15-2004
    Location
    Tokyo, Japan
    MS-Off Ver
    2013 O.365
    Posts
    22,641

    Re: For Each loop taking long to run

    AdvancedFilter...
    Sub test()
        Dim rng As Range
        With Sheets("CMRs 2018").Cells(1).CurrentRegion
            Set rng = .Offset(, .Columns.Count + 2).Range("a1:a2")
            rng(2).Formula = "=or(and(y2<>"""",z2=""""),and(y2="""",w2<>""""))"
            .AdvancedFilter 2, rng, Sheets("CMR Tracking").Range("a1")
            rng.Clear
        End With
    End Sub

  11. #11
    Forum Expert
    Join Date
    10-02-2014
    Location
    USA
    MS-Off Ver
    2016
    Posts
    1,222

    Re: For Each loop taking long to run

    As you have noticed For each loops on a range is slow.

    As other have mentioned your best approach for speed is to either use the autofilter or advanced filter. Autofilter is easier to setup and control, but you have to then copy the results to the desired destination. Advanced filter requires some setup (as the criteria needs to be on sheet if I recall) but it can dump results to a destination which is more efficient than copying the data yourself and its able to handle more complex conditions.

    You also mention loading the results to a listbox on another sheet. Do you mean a drop down validation list, a listbox control, a activex listbox or a listbox in a form? In any case you may consider loading the results into an array, collection or dictionary instead of on sheet into a range. First, it wouldnt increase file size as the results wouldnt be stored on sheet and it would likely be easier to work with.
    Ways to get help: Post clear questions, explain your overall goal, supply as much background as possible, respond to questions asked of you by those trying to help and post sample(s) files.

    "I am here to help, not do it for people" -Me

  12. #12
    Registered User
    Join Date
    02-17-2014
    Location
    Florida
    MS-Off Ver
    Excel 2016
    Posts
    62

    Re: For Each loop taking long to run

    Hi ZerOCool,

    Thanks for the reply and information. I'm attempting to use jindon's AdvancedFilter above your post, but am only getting the first column of data returned in the CMR Tracking sheet. Rather than ask how to fix it (the easy way), I'm working with the code to try and learn.

    I try to do as much as I can without asking for help to try and learn before just getting the answer. I may throw out the "Help" post in a bit but for now, I'll keep at it.

    Thank you for your time and suggestions. I've not used "collection" or "dictionary" before - something new to research!

    Jay

  13. #13
    Forum Expert
    Join Date
    10-02-2014
    Location
    USA
    MS-Off Ver
    2016
    Posts
    1,222

    Re: For Each loop taking long to run

    Quote Originally Posted by Jay S. View Post
    I've not used "collection" or "dictionary" before - something new to research!Jay
    You have before and didnt even know it

    In your For Each loop, you were looping each range object (cell) of the range collection you specified. There are many built in collections. Sheets/Worksheets, Workbooks, Range, Tables, Charts, etc. Most people work with these (and the concept of them) often without ever considering it.

    The concept is no different when dealing with custom collections. You are simply storing like information in the same paradigm as the built in collections, which then let you access them and manipulate them in the same fashions. A benefit of a collection vs an array is that resizing is much easier in a collection. Adding/removing elements is pretty simple. It also allows using the For each construct to loop instead of using a counter and Ubound. The downside is in large data sets collections can be slower than arrays and dictionaries and the values of the items in the collection are read-only.

    Heres a good primer on collections https://excelmacromastery.com/excel-vba-collections/

    A dictionary is kind of like a combination of an array and collection. A dictionary is faster than a collection (and in some cases faster than an array) and it provides the benefits of a collection, plus you can check if items exist in the dictionary already as well as change the values of existing elements. The downside is you either need to early bind and reference the Microsoft Scripting Runtime or late bind (which means VBE may not give you hints about what properties, methods and arguments to use as you type.) A dictionary is also a bit harder in concept to understand.

    Heres a good intor to dictionaries https://excelmacromastery.com/vba-dictionary/

    Each has its place, as you gain more experience programming you will start to see when to use each in your code.

  14. #14
    Valued Forum Contributor
    Join Date
    04-01-2015
    Location
    The Netherlands
    MS-Off Ver
    2003/2007/2010/2016/office 365
    Posts
    880

    Re: For Each loop taking long to run

    try this

    Sub VenA()
      With Sheets("CMRs " & Year(Now))
        .Range("AD2") = "=OR(AND(Y2>0,Z2=0),AND(W2<>"""",X2=0))"
        .Cells(1).CurrentRegion.AdvancedFilter xlFilterCopy, .Range("AD1:AD2"), Sheets("CMR Tracking").Range("A1:Z1")
        .Range("AD2").Clear
      End With
    End Sub

  15. #15
    Forum Guru Norie's Avatar
    Join Date
    02-02-2005
    Location
    Stirling, Scotland
    MS-Off Ver
    Microsoft Office 365
    Posts
    19,643

    Re: For Each loop taking long to run

    Jay

    Give this a try.
    Dim arrIn As Variant
    Dim arrOut() As Variant
    Dim cnt As Long
    
        wsDestination.Range("A2:Z" & lastRowDestination).ClearContents
    
    
        arrIn = Sheets("CMRs 2018").Range("A2", Sheets("CMRs 2018").Range("A" & Rows.Count).End(xlUp).Offset(, 25)).value
    
    
        i = 2
    
        For i = 1 To UBound(arrIn)
        
            If Not IsEmpty(arrIn(i, 25)) And arrIn(i, 26) = "" Or IsEmpty(arrIn(i, 25)) And arrIn(i, 23) <> "" Then
                cnt = cnt + 1
                ReDim Preserve arrOut(1 To 26, 1 To cnt)
                For j = 1 To 26
                    arrOut(j, cnt) = arrIn(i, j)
                Next j
            End If
        Next i
        
        wsDestination.Range("A2").Resize(UBound(arrOut, 2), UBound(arrOut, 1)).value = Application.Transpose(arrOut)
    PS You could actually populate the listbox directly from the array but I'm not sure if you need the CMR Tracking sheet for other purposes so I've dumped the array there rather than do that.
    If posting code please use code tags, see here.

  16. #16
    Registered User
    Join Date
    02-17-2014
    Location
    Florida
    MS-Off Ver
    Excel 2016
    Posts
    62

    Re: For Each loop taking long to run

    Thanks very much ZerOCool.

    I've never heard those two terms (Collection and Dictionary). I appreciate the education and links.

    Jay

  17. #17
    Registered User
    Join Date
    02-17-2014
    Location
    Florida
    MS-Off Ver
    Excel 2016
    Posts
    62

    Re: For Each loop taking long to run

    All,

    Here's what I ended up going with:

    Sub OutstandingWOs()
    Dim lastRowDestination As Long
    Dim wsDestination As Worksheet
    Dim wsSource As Worksheet
    
    Set wsDestination = Sheets("CMR Tracking")
    Set wsSource = Sheets("CMRs " & Year(Now))
    
    lastRowDestination = wsDestination.Range("F" & Rows.Count).End(xlUp).Row
    
    wsDestination.Range("A2:Z" & lastRowDestination).ClearContents
    
      With wsSource
        .Range("AD2") = "=OR(AND(Y2>0,Z2=0),AND(W2<>"""",X2=0))"
        .Cells(1).CurrentRegion.AdvancedFilter xlFilterCopy, .Range("AD1:AD2"), Sheets("CMR Tracking").Range("A1:Z1")
        .Range("AD2").Clear
      End With
    
    Set wsDestination = Nothing
    Set wsSource = Nothing
    
    End Sub
    Once I understood how the code works, it made a lot of sense. I appreciate all your suggestion, education and efforts!

    Jay

  18. #18
    Forum Guru Norie's Avatar
    Join Date
    02-02-2005
    Location
    Stirling, Scotland
    MS-Off Ver
    Microsoft Office 365
    Posts
    19,643

    Re: For Each loop taking long to run

    Jay

    Just curious, did you try the code I posted?

  19. #19
    Valued Forum Contributor
    Join Date
    04-01-2015
    Location
    The Netherlands
    MS-Off Ver
    2003/2007/2010/2016/office 365
    Posts
    880

    Re: For Each loop taking long to run

    @Norie,
    Your code contains a lot of unnecessary declarations and is also extremely slow compared to the advanced fiilter.
    I also miss the added value. Well someone who has tested it.

    See file for a speedtest.CMR FORM.xlsb

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. When Refresh All is taking too long....
    By dd510 in forum Excel Programming / VBA / Macros
    Replies: 0
    Last Post: 10-28-2014, 12:29 PM
  2. taking too long to load2
    By muhdass in forum Excel Programming / VBA / Macros
    Replies: 0
    Last Post: 09-19-2013, 05:22 AM
  3. taking too long to load
    By muhdass in forum Excel Programming / VBA / Macros
    Replies: 7
    Last Post: 09-18-2013, 11:54 PM
  4. Is there anyway to see why ScreenUpdating is taking so long?
    By foxguy in forum Excel Programming / VBA / Macros
    Replies: 4
    Last Post: 10-11-2011, 04:17 AM
  5. Macro taking too long time to run
    By sharmanjali87 in forum Excel Programming / VBA / Macros
    Replies: 2
    Last Post: 12-02-2010, 07:08 AM
  6. Manual Calc taking way too long
    By wbd_kelley@yaho in forum Excel General
    Replies: 2
    Last Post: 05-13-2008, 02:06 PM
  7. [SOLVED] Cell Calculation taking to long
    By Emma in forum Excel Programming / VBA / Macros
    Replies: 1
    Last Post: 01-26-2005, 07:06 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

Search Engine Friendly URLs by vBSEO 3.6.0 RC 1