I am trying create a data set and finding it difficult to do it manually. I just wanted to know if there is way we can do it automatically in Excel.
As shown in the above image I need to do it 52 weeks. For e.g. 201703 ; 201704;201705...... 201752.
Any help in this regard will be greatly appreciated!!
Thanks,
Ganesh
I think you have already identify the pattern of WeekDiff, which always goes from 5 to -5.
Since you have data for 201701, based on them can generate data from 201702 onwards.
You can use below formulae for CRW, Snapweek and WeekDiff cells once inserting data for 201701.
Drag till you get preferred result.
Cell#A14 =IF(A2<>"",A2+1,"")
Cell#B14 =IF(NUMBERVALUE(RIGHT(B2,2))<52,IF(B2<>"",B2+1,""),B2+49)
Cell#C14 =IF(C2<>"",C2,"")
The formula for your weekdiff could be:
=(MIN(DATE(LEFT(A2,4)+1,1,0),DATE(LEFT(A2,4),1,1)-WEEKDAY(DATE(LEFT(A2,4),1,1),2)+RIGHT(A2,2)*7)-MIN(DATE(LEFT(B2,4)+1,1,0),DATE(LEFT(B2,4),1,1)-WEEKDAY(DATE(LEFT(B2,4),1,1),2)+RIGHT(B2,2)*7))/7
But I am not sure you also want the year-weeks be filled automatically, if so try this sub:
Sub tst()
Dim startweek As Long, i As Long, j As Long, k As Long, arr(1 To 624, 1 To 3)
startweek = 201701
For j = 1 To 52
For i = 1 To 12
k = k + 1
If i = 12 Then Exit For
arr(k, 1) = startweek: arr(k, 3) = 6 - i: arr(k, 2) = startweek - arr(k, 3)
If Val(Right(arr(k, 2), 2)) > 52 Then arr(k, 2) = arr(k, 2) - 48
Next i
startweek = startweek + 1
Next j
Sheet1.Cells(2, 1).Resize(UBound(arr), UBound(arr, 2)) = arr
End Sub
I did mine simultaneously with #Surani and got
In A2
=201700+INT((ROW()-2)/11)+1
In C2
=5-MOD(ROW()-2,11)
In B2
=IF((MOD(A2,100)-C2)<1,201652-(C2-MOD(A2,100)),IF((MOD(A2,100)-C2)>52,201800+(MOD(A2,100)-C2)-52,201700+MOD(A2,100)-C2))
but the other solution looks shorter!
Related
I am trying to simplify a code in a Macro for numbering rows of specific columns of excel. Currently I am using
With Sheet1.Range("V6")
.Value = 1
.AutoFill .Resize(V6 + C, 1), xlFillSeries
End With
The macro has already set "C" as a variable that can change each time it is run. I want to simplify the code because I don't know how to loop this to repeat in every third column. I have tried For Loops but i am new to VBA and cannot get the program to run. Looping this would help me becasue I currently have this same code altered 85 differnt times to fill 85 different columns. For example, the next set is
With Sheet1.Range("Y6")
.Value = 1
.AutoFill .Resize(Y6 + C, 1), xlFillSeries
End With
Is there a more simple way this can be accomplished?
An alternate approach using Offset to fill every third column, starting in V6.
Sub MyNumbering()
Dim c As Long, i As Long
c = 100
For i = 0 To 84
With Sheet1.Range("V6").Offset(, i * 3)
.Value = 1
.AutoFill .Resize(c), xlFillSeries
End With
Next i
End Sub
This will iterate every 3rd column starting with column V and post 85 columns of row numbers starting in row 6 and ending at C + 6
Sub mynum()
Dim c As Long: c = 100
Dim j As Long
For j = 22 To 22 + 85 * 3 Step 3
With Sheet1.Range(Sheet1.Cells(6, j), Sheet1.Cells(c + 6, j))
.Formula = "=ROW(1:1)"
.Value = .Value
End With
Next j
End Sub
I am a newbie in Excel VBA Programming. I have a problem which took me more than a week until now to solve it.
If for example I have this data :
85
86
87
88
89
90
91
201
202
203
204
560
561
562
my data before
which has two characteristics, one has +1 difference, and another one has >1 difference. I want my data to be like this:
enter image description here
Could you please help me to find the excel vba code for that? I do really appreciate for your help. Thank you very much.
Place a 1 in B1.In B2 enter:
=IF(A2=A1+1,B1,B1+1)
and copy down:
This simple script will do what you want.
Sub Test()
Dim i As Integer
Dim x As Integer
Dim lastRow As Long
lastRow = UsedRange.Rows.Count
x = 1
For i = 1 To lastRow Step 1
If Range("A" & i + 1) - Range("A" & i) = 1 Then
Range("B" & i).Value = x
Else
Range("B" & i).Value = x
x = x + 1
End If
Next i
End Sub
first question on Stack Overflow here. I'm quite new to VBA so please bear with my question.
I'm trying to run regressions using User Defined Function, and I would like to generate two range variables that are filtered according to a criteria.
For example, in Sheet1 I have:
And I would like to run a regression with Xs and Ys when X is smaller than 0.3.
Previously I tried a code using For loop to assign values to the range:
Dim X As Range
Dim Y As Range
Dim i As Integer
Dim j As Integer
j = 1
With ActiveSheet
For i = 1 To 100
If Cells(i, 1).Value < 0.3 Then
X(j) = Cells(i, 1).Value
Y(j) = Cells(i, 2).Value
End If
j = j + 1
Next i
End With
And apparently it doesn't work so I didn't proceed to the regression part. Could anyone help me correct this?
Alternatively, I've been thinking about whether it's possible to get the whole range of values first and then delete some of them.
Now I have set X and Y ready:
Set X = Range(Cells(1, 1), Cells(7, 1))
Set Y = Range(Cells(1, 2), Cells(7, 2))
But I'm not sure what the possible ways are to delete (not setting them to 0 or empty) some units in these range variables. Could anyone help me with that as well?
Thanks everyone for helping me.
NOTE: My problem was not solved by other similar questions on this as well as other sites. Please have a fair view at my question before judging the same
I am trying to perform a task in which first I have to identify the smallest, 2nd smallest numbers and so on and according to this I have to copy data from one column to another. This will continue until the sum of the copied values becomes grater than or equal to certain value in the sheet (Here row no. for the comparison is given by variable "b"). This will be repeated for 172 different sets which are repeated after every 43 cells.
I have written the following code:
Dim m As Range, k As Double, j As Double, b As Double, lIndex As Double, a As Double
Set m = ActiveSheet.Range("E3:E40")
For i = 1 To 172
j = 1
b = 45 + 43 * (i - 1)
For k = 1 To 38
a = Application.Small(m, j)
lIndex = Application.WorksheetFunction.Match(a, m, 0)
If Cells(b, 7).Value < Cells(b, 1).Value Then
Cells(lIndex, 7).Value = Cells(lIndex, 2).Value
Else
End If
j = j + 1
Next k
Set m = m.Offset(43)
Next i
Now there is an error that pops up saying, Unable to get match property of the worksheet class.
NOTE: I have tried solutions online.
Can there be any other way to do it
OR
Is there something wrong I am doing logically or in the syntax as I am new to excel VBAs and coding itself.
a = Application.Small(m, j) will surely return an Error Code when j is actually bigger that the size of te range m. In your code, the range m = Range("E3:E40") has 38 cells, but j can go as high as 38 * 172.
Then you try to call Match with an error code as the first parameter a. This resuts in run-time error. Note here that Application.Match would result in an error code while WorksheetFunction.Match raises a run-time error.
In all cases, no error should occur in your Match if you had fetched correctly the "kth smallest" element. Without being able to check all of you code, I guess what you wanted here was
a = Application.Small(m, k) ' <--- k, not j
And then no error should occur in *.Match(a, m, 0).
After checking your code:
After getting the smallest value, the next value of j should be a + 1 not j + 1.
Why? because if your smallest value is 4 from (4, 6, 10)
on first loop, j = 1, small will return 4.
on second loop, j = 2, small will still return 4, instead of 6.
I want to copy the cells "A2:A" & patientprofiles + 1 and paste them in the first unused row in column D (i.e., there should be no blank cells between what's already in column D and what I want to paste there, but I also don't want to paste over what's already there). I then want to repeat this process a user-defined number of times (this variable will be called g1_observations). I then want to copy the cells "A" & patientprofiles + 2 & ":A" & 2 * patientprofiles + 1 to the new last used row in column D (i.e., taking into account that I've just pasted patientprofiles number of cells g1_observations number of times at the bottom of column D. I want to continue repeating this process a user-defined number of times (this number of times is defined by the variable numberofgrids).
For example: imagine that the user has defined that there will be three grids. Grid 1 will have 2 observations, Grid 2 will have 3 observations, and Grid 3 will have 4 observations. Also imagine that patientprofiles has been set to 40.
If this is the case, there will already be values in cells D1:D121, so I want to begin pasting in D122. I want to paste the cells A2:A41 (40 cells because patientprofiles = 40) to cells D122:D161; I want to paste the cells A42:A81 to cells D162:D201 and again to D:202:D241; and I want to paste cells A82:A121 to cells D242:D281, again to cells D282:D321, and again to cells D322:D361. I'm pasting each "grid" one less time than the number of observations for that grid, because the first group of observations for all grids is what's contained in cells D2:D121. End example
I'm pretty sure I need to use a nested For...Next loop in order to do this, but I'm having trouble with both the inner and outer loop. I think the outer loop should go something like this:
Dim i as long
For i = 0 to numberofgrids - 1
[insert inner loop here]
Next
As far as the inner loop goes, I'm not really sure what I'm doing because it keeps pasting over itself when I am pasting from two grids. The current code I have uses repeated For...Next loops and doesn't work:
Dim myLastRow as Integer
myLastRow = Worksheets("Work").UsedRange.Rows.Count
Dim j as Long
For j = 1 To g1_observations - 1
If j = 1 Then
Range(Cells(2, 1), Cells((patientprofiles + 1), 1)).Copy _
Destination:=Worksheets("Work").Cells(j * myLastRow + 1, 4)
ElseIf j > 1 Then
Range(Cells(2, 1), Cells((patientprofiles + 1), 1)).Copy _
Destination:=Worksheets("Work").Cells((j + 1) * (myLastRow / 2) + 1, 4)
Else: Range("A1").Select
End If
Next
For j = 1 To g2_observations - 1
If j = 1 Then
Range(Cells(patientprofiles + 2, 1), Cells((2 * patientprofiles + 1), 1)).Copy _
Destination:=Worksheets("Work").Cells(j * myLastRow + 1, 4)
ElseIf b > 1 Then
Range(Cells(patientprofiles + 2, 1), Cells((2 * patientprofiles + 1), 1)).Copy _
Destination:=Worksheets("Work").Cells((b + 1) * (myLastRow / 2) + 1, 4)
Else: Range("A1").Select
End If
Next
It pastes over itself, and sometimes it skips lines. I can't really figure out how to reconcile myLastRow with a loop.
I think the inner loop should probably start off something like this:
Dim j as Long
For j = 0 to gj_observations - 1
Range(Cells(j * XXX + 2, 1), Cells((j + 1) * patientprofiles + 1).Copy _
Destination:=Worksheets("Work").Cells(myLastRow * j + 1) , 4
but I'm having difficulty because the variables are called g1_observations, g2_observations, g3_observations, etc., all the way up to g10_observations, and obviously gj_observations won't work. I want to loop on the number between "g" and "_", but I don't know how to get VBA to read variables that way, or if that's possible at all.
Can anyone help me out here? My mind is spinning from trying to understand the concept of loops, especially with different variables at each level.
Also, side question, how do you tell VBA to do nothing in an If statement? I currently have it selecting A1 by writing Else: Range("A1").Select, but I'm sure there's a better way of doing it.
When you're writing macros, it's a better practice to work with ranges and avoid manipulating cells one at a time in a loop. Your macro will run much faster and the code will be clearer.
If you want to create a set of variables that you can access by number, you would use something called an array. This is a pretty fundamental concept that exists in almost every programming language, so I'll refer you to MSDN or your favorite VBA language reference guide for more details.
Dim ws As Worksheet
Dim lr As Long ' Last Row
Dim szpp As Long ' Size (rows) patient profiles
Dim szgobsrv(2) As Long ' Size (rows) observation groups
Dim i As Long
Dim j As Long
Dim SourceCells As Range
Dim TargetCell As Range
Set ws = Sheets("Work")
szpp = 40
szgobsrv(0) = 1
szgobsrv(1) = 2
szgobsrv(2) = 3
For i = 0 To UBound(szgobsrv)
lr = ws.UsedRange.Row + ws.UsedRange.Rows.Count - 1
' copy the patient profile cells multiple times depending on group size
For j = 0 To szgobsrv(i) - 1
Set SourceCells = ws.[A2].Offset(i * szpp).Resize(szpp)
Set TargetCell = ws.[D1].Offset(lr + j * szpp)
SourceCells.Copy TargetCell
Next
Next
Note the usage of the Resize and Offset methods. These are helpful Range methods that can change the size and position of a range by a fixed amount.
The main problem you are having with values being over written is that youre not using Offset.
Another important thing to remember about nested loops is that the nested loop runs i times per loop of the upper level loop. I am thinking that nested loops here might not be good for you. You could probably just make them all independent loops?
If you want to loop to the number contained within the variable you might want to set that variable equal to a number.
example:
g2_observations =2
For j = 1 To g2_observations - 1
Aside from this I am actuall yhaving difficulty understanding what you need, but hopefully this helps?
numberofgrids = input
i = 1 to numberofgrids
gridCount = gridCount + 1
'Loop Stuff
Case Select gridCount
Case is = 1
'logic
Case is = 2
'logic
Etc etc
End Select
If numberofgrids = gridCount Then
Exit For
End If
Next i