Need help writing a Do Until Loop (VBA)

min9af

New Member
Joined
May 19, 2020
Messages
3
Office Version
  1. 2016
Platform
  1. Windows
Hi all!

I am wondering if it's possible to write a do until loop that would read through all entries of one ID and do a function and then move onto the next ID.
- The IDs are structured XXX.1.0001 (and goes up to XXX.1.0626, but will likely continue to increase)
- My main point of confusion right now is that each ID has a variable number of entries and I need the do until loop to read through all entries before moving onto the next.
- Once I get the do until loop figured out, I'm hoping to add a nested if statement that will allow me to sort entries for each ID by date and a binary variable

Thanks for your help!
 

Excel Facts

Difference between two dates
Secret function! Use =DATEDIF(A2,B2,"Y")&" years"&=DATEDIF(A2,B2,"YM")&" months"&=DATEDIF(A2,B2,"MD")&" days"
Welcome to the Board!

It is difficult to provide specific instruction to a very vague request. I think it will be beneficial for us to see a sample of what your data looks like, and what you are ultimately trying to accomplish.
There are tools here that will allow you to post images. See here: XL2BB - Excel Range to BBCode
 
Upvote 0
Thanks, is this less vague? I have what's on the left and am trying to generate the table on the right (or something similar).

example_for_mrexcel.xlsx
ABCDEFGHIJK
1IDDateTest TypeIDTimepoint 1ABTimepoint 2AB
2XXX.1.00013/31/2020AXXX.1.00013/31/2020104/2/202001
3XXX.1.00014/2/2020BXXX.1.00023/31/2020104/8/202011
4XXX.1.00014/3/2020AXXX.1.00034/6/2020104/7/202010
5XXX.1.00014/15/2020A
6XXX.1.00014/15/2020B
7XXX.1.00023/31/2020A
8XXX.1.00024/8/2020B
9XXX.1.00024/8/2020A
10XXX.1.00024/9/2020A
11XXX.1.00024/10/2020B
12XXX.1.00024/20/2020A
13XXX.1.00034/6/2020A
14XXX.1.00034/7/2020A
15XXX.1.00034/10/2020B
16XXX.1.00034/15/2020A
17
Sheet2
 
Upvote 0
I have done this, but have not work on the specific format you want:

VBA Samples.xlsm
ABCDEFGH
1IDDateTest TypeIDDate
2XXX.1.00103/31/2020AXXX.1.00103/31/20201
3XXX.1.00104/02/2020BXXX.1.00104/02/20201
4XXX.1.00104/03/2020AXXX.1.00104/03/20201
5XXX.1.00104/15/2020AXXX.1.00104/15/202011
6XXX.1.00104/15/2020BXXX.1.00203/31/20201
7XXX.1.00203/31/2020AXXX.1.00204/08/202011
8XXX.1.00204/08/2020BXXX.1.00204/09/20201
9XXX.1.00204/08/2020AXXX.1.00204/10/20201
10XXX.1.00204/09/2020AXXX.1.00204/20/20201
11XXX.1.00204/10/2020BXXX.1.00304/06/20201
12XXX.1.00204/20/2020AXXX.1.00304/07/20201
13XXX.1.00304/06/2020AXXX.1.00304/10/20201
14XXX.1.00304/07/2020AXXX.1.00304/15/20201
15XXX.1.00304/10/2020B
16XXX.1.00304/15/2020A
TestData


The code is as follows:
VBA Code:
Sub FindTestType()
'=============================================
'   Find the test type for each ID and Date
'=============================================
Dim TData As Worksheet
Dim LastRow As Long
Dim ResultRow As Long
Dim DataRow As Long
Dim LastDataRow As Long
Dim LastResultRow As Long

    '===============================
    '   Turn off screen updating
    '===============================
    Application.ScreenUpdating = True
   
    '===================================================
    '   Assign the variable to the worksheet TestData
    '===================================================
    Set TData = ActiveWorkbook.Sheets("TestData")
   
    '============================
    '   Find the last data row
    '============================
    LastRow = TData.Range("A1048576").End(xlUp).Row
   
    '=====================================================
    '   Copy the data columns A and B to column E and F
    '=====================================================
    TData.Range("A1:B" & LastRow).Copy Destination:=TData.Range("E1")
   
    '=========================================
    '   Clear away any existing sort fields
    '=========================================
    TData.Sort.SortFields.Clear
   
        '======================================
        '   Add the first sort field - Col E
        '======================================
        TData.Sort.SortFields.Add2 _
            Key:=Range("E2:E" & LastRow), _
            SortOn:=xlSortOnValues, _
            Order:=xlAscending, _
            DataOption:=xlSortNormal
           
        '=======================================
        '   Add the second sort field - Col F
        '=======================================
        TData.Sort.SortFields.Add2 _
            Key:=Range("F2:F" & LastRow), _
            SortOn:=xlSortOnValues, _
            Order:=xlAscending, _
            DataOption:=xlSortNormal

            '======================
            '   Execute the Sort
            '======================
            With TData.Sort
                .SetRange Range("E1:F" & LastRow)
                .Header = xlYes
                .MatchCase = False
                .Orientation = xlTopToBottom
                .SortMethod = xlPinYin
                .Apply
            End With
           
        '===============================
        '   Remove duplicates, if any
        '===============================
        TData.Range("$E$1:$F$16").RemoveDuplicates _
            Columns:=Array(1, 2), _
            Header:=xlYes
   
    '=======================
    '   Define the:
    '   * Last Data Row
    '   * Last Result Row
    '=======================
    LastDataRow = LastRow   'We found this earlier. Change variable name for clarity
    LastResultRow = TData.Range("E1048576").End(xlUp).Row
   
    '======================================
    '   Run a loop to find the Test Type
    '======================================
    For ResultRow = 2 To LastDataRow
   
        For DataRow = 2 To LastDataRow
       
            '===================================================
            '   Find the data row that matches the result row
            '===================================================
            If TData.Range("E" & ResultRow) = TData.Range("A" & DataRow) And _
               TData.Range("F" & ResultRow) = TData.Range("B" & DataRow) Then
               '====================================================
               '   Check the test type and write to column G or H
               '====================================================
               If TData.Range("C" & DataRow) = "A" Then
                    '===========================
                    '   Add count to column G
                    '===========================
                    TData.Range("G" & ResultRow) = TData.Range("G" & ResultRow) + 1
                   
               ElseIf TData.Range("C" & DataRow) = "B" Then
                    '===========================
                    '   Add count to column H
                    '===========================
                    TData.Range("H" & ResultRow) = TData.Range("H" & ResultRow) + 1
               End If
              
            End If
       
        Next DataRow
       
    Next ResultRow
   
    '===============================
    '   Turn back screen updating
    '===============================
    Application.ScreenUpdating = True


End Sub
 
Last edited by a moderator:
Upvote 0
Thanks so much! Is it possible to copy and paste the test type into columns G & H instead of doing a count? I tried substituting several variations of this into 'Add count to column G'
VBA Code:
 TData.Range("G" & ResultRow) = TData.Range("C" & ResultRow).Copy Destination:=TData.Range("G" & ResultRow)
but I ran into several errors.

Thanks again!
 
Upvote 0
Sorry for the late reply.

Here is the new code. It caters for 10 Timepoints.
You can add more Timepoints if needed (by adding the headings, as well as the CASE statements).
Have fun!


VBA Code:
Option Compare Text

Sub FindTestType()
'=============================================
'   Find the test type for each ID and Date
'=============================================
Dim TData As Worksheet

Dim DataRow As Long
Dim ResultRow As Long

Dim LastDataRow As Long
Dim LastIDRow As Long

Dim ResultID As String
Dim PrevDataID As String
Dim NewDataID As String

Dim TestCountForThisDate As Integer

    '===============================
    '   Turn off screen updating
    '===============================
    Application.ScreenUpdating = True

    '===================================================
    '   Assign the variable to the worksheet TestData
    '===================================================
    Set TData = ActiveWorkbook.Sheets("TestData")
    
    '=============================
    '   Delete previous results
    '=============================
    TData.Columns("E:AZ").EntireColumn.Delete
    
    '============================
    '   Find the last data row
    '============================
    LastDataRow = TData.Range("A1048576").End(xlUp).Row
    
    '=========================================
    '   Clear away any existing sort fields
    '=========================================
    TData.Sort.SortFields.Clear
    
        '======================================
        '   Add the first sort field - Col A
        '======================================
        TData.Sort.SortFields.Add2 _
            Key:=Range("A2:A" & LastDataRow), _
            SortOn:=xlSortOnValues, _
            Order:=xlAscending, _
            DataOption:=xlSortNormal
            
        '=======================================
        '   Add the second sort field - Col B
        '=======================================
        TData.Sort.SortFields.Add2 _
            Key:=Range("B2:B" & LastDataRow), _
            SortOn:=xlSortOnValues, _
            Order:=xlAscending, _
            DataOption:=xlSortNormal

            '======================
            '   Execute the Sort
            '======================
            With TData.Sort
                .SetRange Range("A1:C" & LastDataRow)
                .Header = xlYes
                .MatchCase = False
                .Orientation = xlTopToBottom
                .SortMethod = xlPinYin
                .Apply
            End With
            
    '================================================
    '   Now that the data is sorted by ID and Date
    '   You will copy the ID to column E
    '   then remove the duplicate ID
    '================================================
    TData.Range("A1:A" & LastDataRow).Copy Destination:=TData.Range("E1")
        '=======================
        '   Remove duplicates
        '=======================
        LastIDRow = TData.Range("E1048576").End(xlUp).Row
        TData.Range("$E$1:$E" & LastIDRow).RemoveDuplicates _
            Columns:=1, _
            Header:=xlYes
    
        '================================
        '   Insert the result headings
        '================================
        With TData
            .Range("F1") = "Timepoint 1"
            .Range("G1") = "A"
            .Range("H1") = "B"
            
            .Range("I1") = "Timepoint 2"
            .Range("J1") = "A"
            .Range("K1") = "B"
            
            .Range("L1") = "Timepoint 3"
            .Range("M1") = "A"
            .Range("N1") = "B"
            
            .Range("O1") = "Timepoint 4"
            .Range("P1") = "A"
            .Range("Q1") = "B"
            
            .Range("R1") = "Timepoint 5"
            .Range("S1") = "A"
            .Range("T1") = "B"
            
            .Range("U1") = "Timepoint 6"
            .Range("V1") = "A"
            .Range("W1") = "B"
            
            .Range("X1") = "Timepoint 7"
            .Range("Y1") = "A"
            .Range("Z1") = "B"
            
            .Range("AA1") = "Timepoint 8"
            .Range("AB1") = "A"
            .Range("AC1") = "B"
            
            .Range("AD1") = "Timepoint 9"
            .Range("AE1") = "A"
            .Range("AF1") = "B"
            
            .Range("AG1") = "Timepoint 10"
            .Range("AH1") = "A"
            .Range("AI1") = "B"
            
            'ADD MORE IF NEEDED
            
            '==================================
            '   Format the Timepoint columns
            '==================================
            .Columns("F:F").NumberFormat = "dd/mm/yyyy"
            .Columns("I:I").NumberFormat = "dd/mm/yyyy"
            .Columns("L:L").NumberFormat = "dd/mm/yyyy"
            .Columns("O:O").NumberFormat = "dd/mm/yyyy"
            .Columns("R:R").NumberFormat = "dd/mm/yyyy"
            
            .Columns("U:U").NumberFormat = "dd/mm/yyyy"
            .Columns("X:X").NumberFormat = "dd/mm/yyyy"
            .Columns("AA:AA").NumberFormat = "dd/mm/yyyy"
            .Columns("AD:AD").NumberFormat = "dd/mm/yyyy"
            .Columns("AG:AG").NumberFormat = "dd/mm/yyyy"
            
            '=================================
            '   Format the Test Type values
            '=================================
            .Columns("G:H").NumberFormat = "0"
            .Columns("J:K").NumberFormat = "0"
            .Columns("M:N").NumberFormat = "0"
            .Columns("P:Q").NumberFormat = "0"
            .Columns("S:T").NumberFormat = "0"
            
            .Columns("V:W").NumberFormat = "0"
            .Columns("Y:Z").NumberFormat = "0"
            .Columns("AB:AC").NumberFormat = "0"
            .Columns("AE:AF").NumberFormat = "0"
            .Columns("AH:AI").NumberFormat = "0"
            
            '=================================
            '   Data alignment in the cells
            '=================================
            .Columns("E:AZ").HorizontalAlignment = xlCenter
            .Columns("E:AZ").VerticalAlignment = xlCenter
            
        End With

    '---------------------------------------------------------------------
    '   Next, we need a placeholder to identify the ID (on the results)
    '   Also, as we loop through the data
    '      we have to check whether the
    '         current ID (data) matches the current ID (results)
    '      so that we know to which row we copy the data
    '---------------------------------------------------------------------
    
    '=====================================
    '   Initialize (set initial values)
    '=====================================
    ResultRow = 2
    DataRow = 2
    PrevDataID = TData.Range("A" & ResultRow)
    TestCountForThisDate = 0
    
        '=================================
        '   Loop through the result IDs
        '=================================
        Do While TData.Range("E" & ResultRow) <> ""
            '=============================
            '   Get the ID for this row
            '=============================
            ResultID = TData.Range("E" & ResultRow)
            Debug.Print "ResultRow = " & ResultRow & " - ResultID = " & ResultID
                '===========================
                '   Loop through the data
                '===========================
                Do While TData.Range("A" & DataRow) <> ""
                    '=====================
                    '   Get the Data ID
                    '=====================
                    NewDataID = TData.Range("A" & DataRow)
                    Debug.Print "   Data Row = " & DataRow & " - NewDataID = " & NewDataID
                        '==================================================================
                        '   If the Data ID is the same as Result ID then copy the result
                        '==================================================================
                        If NewDataID = PrevDataID Then
                            '==================================
                            '   Set the TestCountForThisDate
                            '==================================
                            TestCountForThisDate = TestCountForThisDate + 1
                                '===============================
                                '   Copy the Data ID and Date
                                '===============================
                                Select Case TestCountForThisDate
                                
                                    Case 1
                                        TData.Range("B" & DataRow).Copy TData.Range("F" & ResultRow)
                                        If TData.Range("C" & DataRow) = "A" Then
                                            TData.Range("G" & ResultRow) = TData.Range("G" & ResultRow) + 1
                                        ElseIf TData.Range("C" & DataRow) = "B" Then
                                            TData.Range("H" & ResultRow) = TData.Range("H" & ResultRow) + 1
                                        End If
                                        
                                    Case 2
                                        TData.Range("B" & DataRow).Copy TData.Range("I" & ResultRow)
                                        If TData.Range("C" & DataRow) = "A" Then
                                            TData.Range("J" & ResultRow) = TData.Range("J" & ResultRow) + 1
                                        ElseIf TData.Range("C" & DataRow) = "B" Then
                                            TData.Range("K" & ResultRow) = TData.Range("K" & ResultRow) + 1
                                        End If
                                
                                    Case 3
                                        TData.Range("B" & DataRow).Copy TData.Range("L" & ResultRow)
                                        If TData.Range("C" & DataRow) = "A" Then
                                            TData.Range("M" & ResultRow) = TData.Range("M" & ResultRow) + 1
                                        ElseIf TData.Range("C" & DataRow) = "B" Then
                                            TData.Range("N" & ResultRow) = TData.Range("N" & ResultRow) + 1
                                        End If
                                                                
                                    Case 4
                                        TData.Range("B" & DataRow).Copy TData.Range("O" & ResultRow)
                                        If TData.Range("C" & DataRow) = "A" Then
                                            TData.Range("P" & ResultRow) = TData.Range("P" & ResultRow) + 1
                                        ElseIf TData.Range("C" & DataRow) = "B" Then
                                            TData.Range("Q" & ResultRow) = TData.Range("Q" & ResultRow) + 1
                                        End If
                                                                                                
                                    Case 5
                                        TData.Range("B" & DataRow).Copy TData.Range("R" & ResultRow)
                                        If TData.Range("C" & DataRow) = "A" Then
                                            TData.Range("S" & ResultRow) = TData.Range("S" & ResultRow) + 1
                                        ElseIf TData.Range("C" & DataRow) = "B" Then
                                            TData.Range("T" & ResultRow) = TData.Range("T" & ResultRow) + 1
                                        End If
                                
                                    Case 6
                                        TData.Range("B" & DataRow).Copy TData.Range("U" & ResultRow)
                                        If TData.Range("C" & DataRow) = "A" Then
                                            TData.Range("V" & ResultRow) = TData.Range("V" & ResultRow) + 1
                                        ElseIf TData.Range("C" & DataRow) = "B" Then
                                            TData.Range("W" & ResultRow) = TData.Range("W" & ResultRow) + 1
                                        End If
                                        
                                    Case 7
                                        TData.Range("B" & DataRow).Copy TData.Range("X" & ResultRow)
                                        If TData.Range("C" & DataRow) = "A" Then
                                            TData.Range("Y" & ResultRow) = TData.Range("Y" & ResultRow) + 1
                                        ElseIf TData.Range("C" & DataRow) = "B" Then
                                            TData.Range("Z" & ResultRow) = TData.Range("Z" & ResultRow) + 1
                                        End If
                                        
                                    Case 8
                                        TData.Range("B" & DataRow).Copy TData.Range("AA" & ResultRow)
                                        If TData.Range("C" & DataRow) = "A" Then
                                            TData.Range("AB" & ResultRow) = TData.Range("AB" & ResultRow) + 1
                                        ElseIf TData.Range("C" & DataRow) = "B" Then
                                            TData.Range("AC" & ResultRow) = TData.Range("AC" & ResultRow) + 1
                                        End If
                                        
                                    Case 9
                                        TData.Range("B" & DataRow).Copy TData.Range("AD" & ResultRow)
                                        If TData.Range("C" & DataRow) = "A" Then
                                            TData.Range("AE" & ResultRow) = TData.Range("AE" & ResultRow) + 1
                                        ElseIf TData.Range("C" & DataRow) = "B" Then
                                            TData.Range("AF" & ResultRow) = TData.Range("AF" & ResultRow) + 1
                                        End If
                                        
                                    Case 10
                                        TData.Range("B" & DataRow).Copy TData.Range("AG" & ResultRow)
                                        If TData.Range("C" & DataRow) = "A" Then
                                            TData.Range("AH" & ResultRow) = TData.Range("AH" & ResultRow) + 1
                                        ElseIf TData.Range("C" & DataRow) = "B" Then
                                            TData.Range("AI" & ResultRow) = TData.Range("AI" & ResultRow) + 1
                                        End If
                                        
                                    'Add more if required
                                                                
                                End Select
                        
                        Else
                            '==========================================
                            '   Different test ID, so exit this loop
                            '==========================================
                            TestCountForThisDate = 0
                            PrevDataID = NewDataID
                            Exit Do
                        
                        End If
                
                    '===================
                    '   Next Data Row
                    '===================
                    DataRow = DataRow + 1
                
                Loop 'until no more data
        
            '=====================
            '   Next Result Row
            '=====================
            ResultRow = ResultRow + 1
            
        Loop 'until no more result ID
    
    '=========================
    '   Autofit the columns
    '=========================
    TData.Columns("A:AZ").AutoFit
    
    '===============================
    '   Turn back screen updating
    '===============================
    Application.ScreenUpdating = True


End Sub
 
Upvote 0
Here is a screenshot of the result:

Screenshot 2020-06-08 at 12.35.59 PM.png
 
Upvote 0

Forum statistics

Threads
1,214,830
Messages
6,121,839
Members
449,051
Latest member
excelquestion515

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top