do while loop in VBA - vba

I have data that looks like the table shown below. The number of observations in this dataset varies each month. The columns remain the same. I would like to loop my code through each row until the row is empty. I think a do while loop would be appropriate, but I have not been successful in executing it thus far (of note, I am a complete VBA newbie.)
A couple of other notes: The only thing that will change as the code runs through each observation of data is the Range selected in line 2 (I will want to move down to the next row of observations) and the final range selected for the Paste Special step in the final line of the code (again, I will want to move down to the next row of observations with each iteration).
Sample Data:
Sex Age Race Total Cholesterol HDL-Cholesterol Systolic Blood Pressure Treatment for High Blood Pressure Diabetes Smoker
F 50 AA 300 90 200 Y Y Y
M 55 AA 290 90 200 Y Y Y
F 50 AA 300 90 200 N N N
Code that I need to loop through each non-empty row:
Sub ASCVD()
Sheets("Sheet1").Select
Range("A2:I2").Select
Selection.Copy
Sheets("Omnibus").Select
Range("C3").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Range("B13").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Sheet1").Select
Range("J2").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End Sub
Thank you very much in advance for your help!!!

On second thought, what you are really asking is how to use a Do While loop:
Sub ASCVD()
Dim row As Integer
row = 2
Do While ThisWorkbook.Sheets("Sheet1").Cells(row, 1) <> "" 'Loop until first cell is empty
ThisWorkbook.Sheets("Sheet1").Range("A" & row & ":I" & row).Select
Selection.Copy
Sheets("Omnibus").Select
Range("C3").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Range("B13").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Sheet1").Select
Range("J" & row).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
row = row + 1
Loop
End Sub
The code loops throw rows 2, 3, 4, 5 .... and stops when it finds a row where the first cell is empty

Create an example of your desired end result, it is extremely unclear what you want to achieve at the moment. (Right now you are only describing a mess of implementation, not what the big picture is)
Anyway I am assuming all you want to do is transpose your data, this code does the job:
Sub ASCVD()
Dim Data() As Variant
Dim nrow As Integer
Data() = ThisWorkbook.Sheets("Sheet1").Range("A1").CurrentRegion.Value
nrow = UBound(Data(), 1)
ThisWorkbook.Sheets("Omnibus").Activate
DoEvents
'Previous two lines needed so that the .Range(Cells(3.3), ... part works below
ThisWorkbook.Sheets("Omnibus").Range(Cells(3, 3), Cells(16 + 2, nrow + 2)) = Application.WorksheetFunction.Transpose(Data())
'Cells(rownumber, columnnumber). Cells(1,1) is cell A1
'Cells(3, 3) is same as cell C3.
'Cells(16 + 2, nrow + 2) in your example case will be cell F18, the last cell of your data.
'+2 because you want to start from C3, meaning all your data is shifted two cells down and two cells right
End Sub

Related

Copy every 4 column and paste in another sheet Microsoft excel

I am new to VBA. Actually, my objective is to copy every 4 columns with 5 rows one after one to a new worksheet named USD.
Below is my code but it is not working in a loop.
Sub CopyColumns()
Range("A5:D9").Select '**I want to add 4 columns till the end of last column with data**
Selection.Copy
Sheets("Test").Select
Sheets.Add.Name = "USD"
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("Test").Select
**'Sceond loop should be like below**
Range("E5:H9").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("USD").Select
Range("A6").Select '**I need to paste data after last row used every time**
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End Sub
you need a loop and a way to move your selection. For loop look up While because you dont know exactly how many times you want to repeat the code and for variables you can use Offset or directly put them into Cells to specify the selection.
Sub CopyColumns()
Dim iCycle As Long
iCycle = 0
Sheets.Add.Name = "USD"
Sheets("Test").Select
While Range("A5").Offset(0, iCycle * 4).Value <> "" 'checks if there are any values left to be copied
Range("A5:D9").Offset(0, iCycle * 4).Copy 'Offset moves whole selection by 4 columns to the right every time
Sheets("USD").Select
Sheets("USD").Range(Cells(1 + iCycle * 5, 1), Cells(1 + iCycle * 5, 4)).PasteSpecial Paste:=xlPasteValues 'Cells can also be used to specify selection based on variable
Sheets("Test").Select
iCycle = iCycle + 1
Wend
End Sub

Loop through columns names : For variable = A to Z

is it possible to loop on column letters?
For col = A to Z
column(col:col).select
selection.copy
Next
Or am I oblige to use a function to transform letters into numbers?
To convert Formulas to Values:
Dim cols As Range, c As String
Set cols = UsedRange.Columns
For Each c In Split("N Q T") ' add the rest of the column letters
cols(c).Value = cols(c).Value ' or .Value2 if no dates or currencies in the range
Next
If it is every third column from column N, another approach can be:
Dim col As Range, i As Long
Set col = UsedRange.Columns("N")
For i = 1 To 17 ' to repeat 17 times
col.Value = col.Value
Set col = col.Offset(, 3)
Next
No need to transform letters into numbers as you can pass letters to Columns and Cells:
Columns("B") 'the same as Columns(2)
Cells(1, "B") 'same as Cells(1, 2)
However looping through letters is kind of a hassle and you'd have to transform a number into a letter first, for example using Chr(64 + Num)
I don't know if it take a lot of calculating time but I actually have
Columns("N:N").Select
selection.Copy
selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Columns("Q:Q").Select
selection.Copy
selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Columns("T:T").Select
selection.Copy
selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
I have 17 time this group of rows, do you think it's a huge waste of time?
EDIT
answer with the link in the comment below, thanks to #Rdster
I suggest one of these two solutions :
1- The Column A is the first column, and Z is the 26th column
'Declaration
Dim iFirstCol as integer
Dim iLastCol as integer
iFirstCol = 1 'the first column (A)
iLastCol = 26 'the last column (Z)
'Looping
FOR col = iFirstCol to iLastCol
Columns(col:col).Select
Selection.Copy
'....
LOOP col
2- The ASCII values of the letters A to Z are 65 to 90.
'Declaration
Dim Cols as string
Your loop can be easily transformed into:
'Looping
FOR col = 65 to 90
Cols=CHR(col) & ":" & CHR(col)
Columns(Cols).Select
Selection.Copy
'...
LOOP col
Hope this can help!

VBA transpose multiple times

I am currently working on a big set of data downloaded from Morningstar Direct. I need help with a macro that can change the exported document from horizontal to vertical. I have tried all the functions in excel without any luck, so i think i need a macro for this operation.
For example:
From:
Data1-2000 Data1-2001 Data1-2002 ... Data1-2016 Data2-2000 Data2-2001 and so on
To:
Data1-2000
Data1-2001
...
Data1-2016
Data2-2000
Data2-2001
...
Every datavariable goes from 2000 to 2016. We have more then 500 tickers that need the same transformation. Is there any VBA code that can do this for me? It will save my life (at least my Easter)!
**Addedum from OP's answer post:
I have made this macro:
Sub Flip()
'
' Flip Macro
'
Sheets("S&P 500 Constituents").Select
Range("I2:X2").Select
Selection.Copy
Sheets("Sheet1").Select
Range("D2").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Sheets("S&P 500 Constituents").Select
Range("AB2:AQ2").Select
Selection.Copy
Sheets("Sheet1").Select
Range("E2").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Sheets("S&P 500 Constituents").Select
Range("AR2:BG2").Select
Selection.Copy
Sheets("Sheet1").Select
Range("F2").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Sheets("S&P 500 Constituents").Select
Range("BH2:BW2").Select
Selection.Copy
Sheets("Sheet1").Select
Range("G2").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Sheets("S&P 500 Constituents").Select
Range("BX2:CM2").Select
Selection.Copy
Sheets("Sheet1").Select
Range("H2").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
End Sub
As you can see everything is taken from row 2 in my S&P500 sheet, and then transposed into sheet1.
How can i make this macro repeat the same operation on row 3, 4, 5 ... 518?
Try the INDEX function.
=INDEX($1:$1, 1, ROW(1:1))
  
Addendum: VBA strip & transpose
Dumping the values from the S&P 500 Constituents worksheet into a two-dimensioned variant array and processing the reorientation in-memory to a second array would be the most expedient method.
Sub Flip()
' Flip Macro
Dim v As Long, val As Variant, vals As Variant
Dim a As Long, b As Long, stp As Long
stp = 16
ReDim val(1 To stp, 1 To 1)
With Worksheets("S&P 500 Constituents")
With .Range(.Cells(2, "I"), .Cells(Rows.Count, "CM").End(xlUp))
vals = .Value2
End With
End With
With Worksheets("Sheet1")
For a = LBound(vals, 1) To UBound(vals, 1)
For b = LBound(vals, 2) To UBound(vals, 2) - stp Step stp
For v = 1 To stp
val(v, 1) = vals(a, b - ((b > 1) * 3) + (v - 1))
Next v
.Cells(2, "D").Offset((a - 1) * stp, Int(b / stp)).Resize(stp, 1) = val
Next b
Next a
End With
End Sub
I've intentionally avoided the use of the native TRANSPOSE function as it has limitations for size that are more suited to an .xls than an .xlsx. The maths that supply the looped reorientation have been derived from your sample code's first row.

VBA- Why End(xlDown) will take me to the very bottom of my excel

The assignment requires me to run the Monte Carlo result 1000 times. I already create a row of 30 years values(B5:AE5), and I want to repeat the process 1000 times. Every time, there will be a new row comes out, and all the values will be random.
Below is my code, for some reason, it will go to the very bottom of my excel sheet. I want the second row of 30 years values inside (B6:AE6).
Sub Macros()
Dim trail As Long
trail = InputBox("Enter the number of time you want to simulate this Macros", "Macros", "10")
For i = 1 To trail
Application.CutCopyMode = False
Range("B5").Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
Selection.End(xlDown).Select
Selection.Offset(-1, 0).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Selection.PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
Range("A4").Select
Selection.End(xlDown).Select
Selection.Copy
Selection.Offset(1, 0).Select
ActiveSheet.Paste
Application.CutCopyMod = False
Next i
Range("B4").Select
End Sub
Thank you sooo much!
To answer your question about why your End(xlDown) takes you to the end of the sheet, the Selection.End(xlDown).Select is similar to pressing Ctrl+Down on the spreadsheet. (Likewise Selection.End(xlToRight)).Select is similar to pressing Ctrl+Right.)
Hence if you are on an empty sheet, or if all the cells beneath the active (or referenced) cell are empty, then pressing Ctrl+Down will bring you to the last row.
All that said, you can avoid that whole issue and improve your code significantly by
Removing all the Select statements and work directly with the range objects.
Using the defined range (B5:AE5) since you know what it is.
Just using the counter to resize the range to to paste the values and formats (and eliminate the loop).
See the code below:
Sub Macros()
Dim trail As Long
trail = InputBox("Enter the number of time you want to simulate this Macros", "Macros", "10")
With Range(Range("B5"), Range("AE5"))
.Copy
.Offset(1).Resize(trail - 1, 30).PasteSpecial xlPasteValues
.Offset(1).Resize(trai1 - 1, 30).PasteSpecial xlPasteFormats
End With
With Range("A5")
.Copy .Offset(1).Resize(trail - 1)
End With
'if you don't need to copy the formats you can change the above With statements to just this:
'With Range("A5:BE5")
' .Offset(i).Resize(trail - 1,31).Value = .Value
'End With
End Sub
It sounds like you want to place formulas in the selected number of rows.
Sub Frmla()
Dim i As Long
i = InputBox("enter Number")
Range("B6:AE" & 5 + i).FormulaR1C1 = "=R[-1]C*0.7"'whatever the formula is
End Sub

VBA: Weekly updated dashboard. Copy data for Trendline. EXCEL

I've managed to create an easy to update dashboard in Excel using VBA. It's pretty solid, but I require a weekly updated trendline to add to this data.
What i'd like is a macro that does the following:
Write data to range X (e.g. A1:A5)
Copy data from range X to Range Y (e.g. A10:A15)
And then when I run step 1 and 2 again
Write data to range X (overwrite data in X A1:A5)
Copy Data from range Y to range Y+1 (e.g. B10:B15)
repeat ad infinitum (each time moving one column to the right)
What I get is that i need to define the column line as an integer and then refer to it.
(e.g.
Sub Trend()
Dim i As Integer
i = 2
Sheets("Data").Select
Range("A1:A5").Select
Selection.Copy
Sheets("Trendline data").Select
ActiveSheet.Cells(1, i).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("Data").Select
i = i + 1
End Sub
However repeating this macro does not increment i for me.
~~Also column 2 is filled completely with a repeat of the data in (Data!A1:A5)~~
This is fixed with an update to the code.
Pretty much what I need to fix is that The line
"Dim i As integer"
i = 2
becomes
"Dim i As integer"
i = 3
Permanently, and repeat the next time for i = 4, i = 5 etc.
After that for me it is easy to create a line chart from this range
Thank you.
edit: wrote what I thought would work, but apparently doesn't
Edited :
What about that?
Sub Trend()
Dim i as integer
If Sheets("Data").Cells(1,1).Value = "" Then
Sheets("Data").Cells(1,1).Value = 1
End if
i = Sheets("Data").Cells(1,1).Value
Sheets("Data").Select
Range("A1:A5").Select
Selection.Copy
Sheets("Trendline data").Select
ActiveSheet.Cells(1, i).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Sheets("Data").Select
Sheets("Data").Cells(1,1).Value = i + 1
End Sub