Creating a loop to fill data?

imsyun

New Member
Joined
Jun 29, 2022
Messages
9
Office Version
  1. 365
Platform
  1. MacOS
Hi all, I've been tasked to clean a dataset and prepare it for SPSS which doesn't handle blank rows well. The dataset looks something like this:
93bKVT.jpg


Basically, there are people visiting each with their own ID and each row is a visit. I have to copy the DOB, sex, and calculate age at time of visit for each person. So something like the image below which I've been doing manually. There are also random gaps throughout because of other data.

p98TjB.jpg

However, the task is very repetitive, especially with so much data. I'm sure there's a faster way to do it but I'm not sure how. I tried searching online but I haven't had much luck, probably because I don't know how to describe the issue.

I would appreciate any tips or what I should be searching to find possible solutions. Thanks!
 

Excel Facts

Copy PDF to Excel
Select data in PDF. Paste to Microsoft Word. Copy from Word and paste to Excel.
It is hard to work with pictures. It would be easier to help if you could use the XL2BB add-in (icon in the menu) to attach a screenshot (not a picture) of your sheet. Alternately, you could upload a copy of your file to a free site such as www.box.com or www.dropbox.com. Once you do that, mark it for 'Sharing' and you will be given a link to the file that you can post here. Explain in detail what you want to do referring to specific cells, rows, columns and sheets using a few examples from your data (de-sensitized if necessary).
 
Upvote 0
Book1
ABCDEFG
1New IDVisit IDPerson No.Visit No.DOBSexAge
211722/4/0823/12/1965Male42.1163587
312721/27/09
4137212/8/09
5147211/19/10
6  
7  
8  
9  
10  
11  
1221743/7/0826/01/1976Female
1322741/27/09
1423741/21/10
1524741/6/11
1625745/4/12
1726744/22/13
1831801/29/0816/09/1997Male
1932805/12/09
2033803/25/10
21  
Sheet1
Cell Formulas
RangeFormula
A2:A21A2=IF(C2="","",IF(COUNTIF($C$2:C2,C2)>1,MAX($A$1:A1),MAX($A$1:A1)+1))
B2:B21B2=IF(COUNTIF($C$2:C2,C2),COUNTIF($C$2:C2,C2),"")
G2G2=(D2-$E2)/365.25


So for example, for DOB (col E) and Sex (col F) for Person No. 72, their details only appear in E2 and F2 (visit 1), but I'd like to have these details show for every visit (E2:E5 and F2:F5). So far, I've just been dragging and pasting the data for each patient so it's a bit time-consuming.

Similarly, for Age (col G), I'd like to do the same but this time there is a formula involved to calculate the age of the person at each visit. I'm using the formula to calculate the age (D2-E2)/365.25. I don't know how when calculating G2, if there's a way to automatically change the DOB to the next person's without having to do it manually.

I'm trying to create what is shown below with possible formulas or macros.

Book1
GHIJKLM
1New IDVisit IDPerson No.Visit No.DOBSexAge
211722/4/0823/12/1965Male42.1163587
312721/27/0924/12/1965Male43.0937714
4137212/8/0925/12/1965Male43.9534565
5147211/19/1026/12/1965Male44.8980151
6  
7  
8  
9  
10  
11  
1221743/7/0826/01/1976Female32.1122519
1322741/27/0927/01/1976Female33.0020534
1423741/21/1028/01/1976Female33.982204
1524741/6/1129/01/1976Female34.9377139
1625745/4/1230/01/1976Female36.2600958
1726744/22/1331/01/1976Female37.2238193
1831801/29/0816/09/1997Male10.3682409
1932805/12/0917/09/1997Male11.6495551
2033803/25/1018/09/1997Male12.5147159
Sheet1
Cell Formulas
RangeFormula
G2:G20G2=IF(A2="","",IF(COUNTIF($A$2:A2,A2)>1,MAX($G$1:G1),MAX($G$1:G1)+1))
H2:H20H2=IF(COUNTIF($A$2:A2,A2),COUNTIF($A$2:A2,A2),"")
M2:M5,M12:M20M2=(J2-$K2)/365.25


Thank you :biggrin:
 
Upvote 0
There may be more efficient ways of coding it, but here is one way that should do what you want:
VBA Code:
Sub MyPopulateData()

    Dim lr As Long, r As Long
    
    Application.ScreenUpdating = False
    
'   Find last row in column A with data
    lr = Cells(Rows.Count, "A").End(xlUp).Row
    
'   Loop through all rows, starting on row 2
    For r = 2 To lr
'       Check for data in column A and blank in column G
        If (Cells(r, "A") <> "") And (Cells(r, "G") = "") Then
'           Populate formula in column G
            Cells(r, "G").FormulaR1C1 = "=(RC[-3]-RC5)/365.25"
'           Check for values in columns E and F
            If Cells(r, "E") = "" Then
'               Copy values from row above
                Range(Cells(r - 1, "E"), Cells(r - 1, "F")).Copy Cells(r, "E")
            End If
        End If
    Next r
    
    Application.ScreenUpdating = True
    
    MsgBox "Macro complete!"
    
End Sub
 
Upvote 0
Hello. Thanks for your response. It seems to be working for the spreadsheet I shared. I tried to use the script for the actual data and changed a couple of the column names:

VBA Code:
Sub MyPopulateData()

    Dim lr As Long, r As Long
    
    Application.ScreenUpdating = False
    
'   Find last row in column A with data
    lr = Cells(Rows.Count, "A").End(xlUp).Row
    
'   Loop through all rows, starting on row 2
    For r = 2 To lr
'       Check for data in column A and blank in column G
        If (Cells(r, "A") <> "") And (Cells(r, "H") = "") Then
'           Populate formula in column G
            Cells(r, "H").FormulaR1C1 = "=(RC[-4]-RC5)/365.25"
'           Check for values in columns F and G
            If Cells(r, "F") = "" Then
'               Copy values from row above
                Range(Cells(r - 1, "F"), Cells(r - 1, "G")).Copy Cells(r, "F")
            End If
        End If
    Next r
    
    Application.ScreenUpdating = True
    
    MsgBox "Macro complete!"
    
End Sub

When I run it, the age formula (col H) doesn't seem to work properly for the 3rd person onwards (row 18). The formula doesn't work for the top row (visit 1) for each person but it is calculated correctly from visit 2 onwards. For sex (col G), it worked for the first participant (rows 1-5), but for the rest, it either left it as before or it disappeared.

current-wd-patient_V2_20220617 copy_saved with macro.xlsm
ABCDEFGH
1Subject IDVisit IDPerson IDVistDOBDate 1SexAge
211725/6/1123/10/197227/07/2011Male38.5325
312723/5/1323/10/197227/07/2011Male40.3641
4137212/8/1823/10/197227/07/2011Male46.1246
5147211/19/1923/10/197227/07/2011Male47.0719
6  
7  
8  
9  
10  
11  
1221753/7/0611/02/20006.06708
1322751/27/0911/02/20008.96099
1423751/21/1111/02/200010.9432
1524751/6/1111/02/200010.9021
1625755/4/1911/02/200019.2252
1726754/22/1311/02/200013.1937
1831821/29/0817/05/199001/03/2015Male=(RC[-4]-RC5)/365.25
1932825/12/1117/05/199001/03/2015Male20.9856
2033823/25/1317/05/199001/03/2015Male22.8556
21  
22  
23  
24  
25418414/01/193020/11/2008Male=(RC[-4]-RC5)/365.25
2651853/10/0829/09/194015/12/2008Male=(RC[-4]-RC5)/365.25
27  
28  
29  
3061873/17/0814/10/1950=(RC[-4]-RC5)/365.25
31  
327181209/05/1943=(RC[-4]-RC5)/365.25
33818134/28/0803/06/1930=(RC[-4]-RC5)/365.25
349181414/09/1989=(RC[-4]-RC5)/365.25
351018152/5/0903/01/192513/01/2016Female=(RC[-4]-RC5)/365.25
36  
37  
38  
391118162/3/0908/12/1937=(RC[-4]-RC5)/365.25
40  
41  
421218174/12/0803/10/196929/06/2017Male=(RC[-4]-RC5)/365.25
431228175/19/0803/10/196929/06/201738.6256
441238175/21/0903/10/196929/06/201739.6304
451248176/20/0903/10/196929/06/201739.7125
461258175/16/1103/10/196929/06/201741.6153
Data
Cell Formulas
RangeFormula
A2:A46A2=IF(C2="","",IF(COUNTIF($C$2:C2,C2)>1,MAX($A$1:A1),MAX($A$1:A1)+1))
B2:B46B2=IF(COUNTIF($C$2:C2,C2),COUNTIF($C$2:C2,C2),"")
H2:H5,H43:H46,H19:H20,H12:H17H2=(D2-$E2)/365.25
Cells with Conditional Formatting
CellConditionCell FormatStop If True
1:1048576Expression=IFBLANK($A2)textYES
1:1867Expression=MOD($A1,2)=0textNO
1:1867Expression=MOD($A1,2)=1textNO


Similar to what I need to do for the sex column, I need to do it for other variables. Could you explain this line of code as I don't full understand?
' Check for values in columns E and F If Cells(r, "E") = "" Then ' Copy values from row above Range(Cells(r - 1, "E"), Cells(r - 1, "F")).Copy Cells(r, "E") End If


Thanks again.
 
Upvote 0
Why do you keep changing the layout (columns) of the file?
The last three images you posted are all different structures.
It is very hard to right code for you if things keep changing.

Can you post a new image of your ACTUAL strucutre, with data BEFORE the macro has been run, so I can test it and amend it for that?
 
Upvote 0
Apologies for the continuous changes. The one below is the actual structure of the data set, though I have removed some identifiable data which didn't need any changes so I hope it's okay now

Book3
ABCDEFGHIJKLMNO
1Subject IDVisit IDPIDVisit DateDOBDateSexAgeTime since 1st visit (days)NumberCharY/NIgnore ColIgnore ColStatus
211726/5/1123/10/197227/07/2011Male017AYActive
312725/3/13698
413728/12/182625
5147211/19/193089
6  
7  
8  
9  
10  
11  
1221753/7/0611/02/2000Female018BYCancelled
1322751/27/091057
1423751/21/111781
1524751/6/111766
1625755/4/194806
1726754/22/132603
1831821/29/0817/05/199001/03/2015Male19BNCancelled
1932825/12/09
2033823/25/10
Sheet1
Cell Formulas
RangeFormula
A2:A20A2=IF(C2="","",IF(COUNTIF($C$2:C2,C2)>1,MAX($A$1:A1),MAX($A$1:A1)+1))
B2:B20B2=IF(COUNTIF($C$2:C2,C2),COUNTIF($C$2:C2,C2),"")
I2:I5I2=D2-$D$2
I12:I17I12=D12-$D$12
Cells with Conditional Formatting
CellConditionCell FormatStop If True
A1:O26Expression=IFBLANK($A2)textYES
A1:O26Expression=MOD($A1,2)=0textNO
A1:O26Expression=MOD($A1,2)=1textNO


What I'm trying to do is:
1. Get the same data to appear for the same person for columns E (DOB), F (Date- not all people have one), G (Sex), J (Number), K (Char), L (Y/N) and O (Status).
2.
a) Create a formula for Age for each participant at the time of visit for column H (Col D which is Visit date - Col E DOB)
b) Create a formula for Time since the first visit (e.g for the first person's second visit - D3 - $D$2). The formula is there at the moment for just the first 2 participants.

I appreciate your help
 
Upvote 0
This seems to work on your latest sample data:
VBA Code:
Sub MyPopulateData()

    Dim lr As Long, r As Long
    
    Application.ScreenUpdating = False
    
'   Find last row in column A with data
    lr = Cells(Rows.Count, "A").End(xlUp).Row
    
'   Loop through all rows, starting on row 2
    For r = 2 To lr
'       Check for data in column A
        If (Cells(r, "A") <> "") Then
'           Check to see if column E is blank
            If (Cells(r, "E") = "") Then
'               Copy columns E to O
                Range(Cells(r - 1, "E"), Cells(r - 1, "O")).Copy Cells(r, "E")
            Else
'               Populate formulas in columns H and I
                Cells(r, "H").FormulaR1C1 = "=(RC[-4]-RC[-3])/365.25"
                Cells(r, "I").FormulaR1C1 = "=RC[-5]-MINIFS(C[-5],C[-8],RC[-8])"
            End If
        End If
    Next r
    
'   Format columns H and I as number
    Columns("H:H").NumberFormat = "0.0000"
    Columns("I:I").NumberFormat = "0"

    Application.ScreenUpdating = True
    
    MsgBox "Macro complete!"
    
End Sub
 
Upvote 0
Solution

Forum statistics

Threads
1,214,613
Messages
6,120,515
Members
448,968
Latest member
Ajax40

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