Search code examples
excelnested-loopsvba

VBA nested loops exiting early


I have a vba script which is supposed to copy data from one sheet to another. It does by means of three nested for loops. Stepping through the code in debugging these appear to work perfectly, but when the vba script is run they appear to stop too early. Otherwise the vba script works.

I have been staring at this for hours and cannot for the life of me see what would cause the loops to stop early. I'm hoping the solution is something simple I've missed, but I am at a genuine loss, not for the first time since I started this.

The sheet is organised as follows:

Sheet1, contains the data to be copied.

  • Each row contains a seperate response, of which there are 55 in the test data
  • The sheet contains nine blocks of data, named Episode 1-9. Each episode contains column where an integer represent a start, end and interval time.
  • In the test data each episode is identical except for the start/end times.
  • The maximum value for EndTime is 36
  • The test data is over the first four Episode blocks only, so Episode4 contains EndTime=36 for each row

Sheet2, where the data is to go -First column contains each RespondentID copied over 36 rows -Second column contains numbers 1-36, thus representing that time slot for that respondent -11 Columns after that contain the area where the data copied from sheet1 for that Respondent/Time is put. These 36x11 areas are named "Response1-55" in the test data

The logic of the vba script is as follows:

Counters: - n counter for number of respondents - r counter for number of episodes - i counter for rows within the responses being copied to.

->For each response (starting with n=1 to Respondents)
--> Select the first episode (Starting with r=1 to 9)
--->For each episode
--->Read the start, end and interval times
--->Starting from i = Start to i=End copy the relevant cells from the n'th row of the r'th episode
--->Copy those cells to the i'th row of the current response on sheet2
--->When you reach the EndTime of the current episode, go to the next one (next r)
-->If the episode you just finished has 36 as its EndTime then go to the next response, or continue till you run out of episodes.
->Next Response

In debugging the code appears to do exactly this.

However when I run the vba script on the test sheet it works only for episodes 1 and 2. The data from episodes 3 and 4 is not copied. Nothing is copied in its place, and the data which IS copied is correct in every respect. There are no error messages at any point.

If anyone could suggest why this might be happening I would build unto them an actual church. The answer could also be added here: https://stackoverflow.com/questions/119323/nested-for-loops-in-different-languages Which does not yet have a section for VBA.

A link to the test sheet is here: http://dl.dropbox.com/u/41041934/MrExcelExample/TornHairExampleSheet.xlsm

The relevant part of the code is here

Sub PopulateMedia()
    Application.ScreenUpdating = False

    'Count the total number of response rows in original sheet
    Dim Responses As Long, n As Integer, i As Integer, r As Integer
        Responses = (Sheets("Sheet1").UsedRange.Rows.Count - 3) ' equals 55 in test sheet

    'For each response...
    For n = 1 To Responses
        i = 1 'Reset i for new response
            Dim curr_resp As Range
                Set curr_resp = Sheets(2).Range("Response" & n) 'Define a range containing all response data

            For r = 1 To 9  'For each episode...
                Dim curr_ep As Range 'Define a range containing episode data for all responses
                    Set curr_ep = Sheets(1).Range("episode" & r)

                Dim Stime As Integer, Etime As Integer, Itime As Integer 'Variables contain start, end and inter-episode times
                    Stime = curr_ep.Cells(n, 1)
                    Etime = curr_ep.Cells(n, 17)
                    Itime = curr_ep.Cells(n, 19)

                    For i = Stime To (Etime + Itime) 'for each time-slot...
                        If i <= Etime Then
                          Dim a As Variant
                            a = curr_ep.Range(curr_ep.Cells(n - 3, 1), curr_ep.Cells(n - 3, 11))
                            curr_resp.Rows(i) = a 'Copy data from above current episode to current response for slots between Stime and Etime
                        End If
                    Next i
                If Etime = 36 Then Exit For
             Next r
     Next n

    Application.ScreenUpdating = True
End Sub

To disclose, I have already had help on this project from this site, VBA copy from a union of two ranges to a row of another range but the code has been changed slightly since then and this is a different problem.

Once more, thank you enormously for any help which might come of this. I have been staring at this for hours and do not see where the error is. Any guidance at all greatly appreciated.


Solution

  • I would post this as a comment if I could but this is too long. So here it is as a query /potential solution

    I think your range references are the issue

    The code below is a cut-down version of your code

    curr_ep is a named range of episode1. It has a range address of $Y$4:$AQ$58

    When you loop through the a variant you are setting a range with this syntax
    a = curr_ep.Range(curr_ep.Cells(n - 3, 1), curr_ep.Cells(n - 3, 11))
    which is equivalent to a = curr_ep.Range("Y2:AQ2")

    which means you are actually looking at AW2:BG2 not Y2:AQ2 which is what I think you may have intended, i.e. you are building in an unintended offset

    Sub PopulateMedia()
        n = 1
        r = 1
        Dim curr_ep As Range
        Dim curr_test As Range
        Set curr_ep = Sheets(1).Range("episode" & r)
        Set curr_test = curr_ep.Range(curr_ep.Cells(n - 3, 1), curr_ep.Cells(n - 3, 11))
    End Sub
    

    enter image description here