I need to apply the following IF functions to every row in columns J, L, and S so that the correct date value is printed in the corresponding cell in row T. For example, cell T2 will have a date printed in it based on the outcome of running these IF functions on J2, L2, and S2; cell T3 will have a date printed in it based on the outcome of running these IF functions on J3, L3, and S3; and so on. Here's what I have got:
Sub Test1()
Set firstDate = Range("S2")
If Range("J2") = "GS/CA/SL/GW" Then
If Range("L2") = "1" Or "2" Or "3" Then
Range("T2") = DateAdd("ww", 52, firstDate)
End If
If Range("L2") = "4" Or "5" Or "6" Then
Range("T2") = DateAdd("ww", 104, firstDate)
End If
If Range("L2") = "7" Or "8" Or "9" Then
Range("T2") = DateAdd("ww", 156, firstDate)
End If
End If
End Sub
It works on one set of cells at a time if I just redefine all the ranges, but I thought there must be an easier way than pasting and editing the code ~3500 times for all the rows I have to run it on. Any help would be appreciated!
If I follow your question correctly I believe you just need a simple loop to adapt your current code.
Try this:
Sub loopDate()
Application.ScreenUpdating = False
Dim LastRow As Integer
LastRow = Cells.Find(What:="*", After:=[A1], SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
Dim firstDate As Range
Dim i As Long
For i = 2 To LastRow
If Range("J" & i) = "GS/CA/SL/GW" Then
Set firstDate = Range("S" & i)
Select Case Range("L" & i)
Case 1 To 3
Range("T" & i) = DateAdd("ww", 52, firstDate)
Case 4 To 6
Range("T" & i) = DateAdd("ww", 104, firstDate)
Case 7 To 9
Range("T" & i) = DateAdd("ww", 156, firstDate)
End Select
End If
Next i
Application.ScreenUpdating = True
End Sub
Note that I started the loop at row 2 since that's what your example used and go until the last used row in column A. I also changed your if logic to a select case statement for improved readability.
You may want to just use an equation in cell T? instead of using VBA but since I don't know the details I'll assume you have a good reason.
Related
Source code:
Dim TH As Double
Lr = Sheet1.Cells(Rows.Count, 1).End(xlUp).Row
'starting point
sRow = 2
'Loop in all cells
For i = sRow To Lr
'check if cell value are not same
If Cells(i, 1).Value <> Cells(i + 1, 1) Then
'if not same then merge all the above cells
Range("I" & sRow, "I" & i).Resize(, 7).Select
TH = Application.WorksheetFunction.Sum(Selection)
**If TH <> 40 Then**
Range("A" & sRow, "A" & i).Interior.Color = RGB(255, 0, 0)
End If
In this Code:
If TH <> 40 Then condition not working when ever the TH is Calculated on Decimal Numbers.
Such as 3.60,0.80,4.60 Sum is coming as 40 when use SUM Function but If Condition is not getting fulfilled.
Please Help
I have tried this, putting decimals all over and it works:
Sub TestMe()
Dim lr As Long
Dim TH As Double
Dim i As Long
lr = 10
For i = 1 To lr
If Cells(i, 1).Value <> Cells(i + 1, 1) Then
Range("I" & 6, "I" & i).Resize(, 7).Select
TH = Application.WorksheetFunction.Sum(Selection)
If TH <> 40 Then
Range("A" & 6, "A" & i).Interior.Color = RGB(255, 0, 0)
End If
End If
Next
End Sub
Thus, probably the problem is the way you put the decimals. In some systems (German or French), the decimal separator is ,, while in English systems it is a point - .. Thus, you might be using the wrong one.
Column has Date with Hours & minutes (Ex:2018-02-16T00:00:20.488Z[UTC]). I want to Filter data every 30 minutes using VBA.
For Ex, first iteration should give me all data between 00:00 to 00:30 minutes of data. I tried the below code;
Dim t As String
t = "T0"
cnt = 4
For n = 1 To 23
ActiveSheet.Range("$A$1:$P$1000000").AutoFilter Field:=2, Criteria1:= _
">=" & FromTime & t & n & ":00", Operator:=xlAnd, Criteria2:=" <= " & FromTime & t & n & ":30"
Next n
When ran, filter will be applied see image
.
Data will not be filtered. However, manually if i change from And to Or I get all relevant data.
What is wrong with my Code?
Column has Date with Hours & minutes (Ex:2018-02-16T00:00:20.488Z[UTC]).
No, it does not. You have a column with a bunch of strings that represent coded date, time and timezone information; something like a Twitter feed timestamp. In order to deal with the pieces as real dates and real times (optionally offset to the local timezone) you will have to parse out the information.
It is probably best to parse and convert the strings-that-look-like-datetimes to actual datetimes¹ before you do any further work but you can run through the strings, parsing to true datetimes on-the-fly and collect matching strings in a dictionary. The dictionary's key values can be used as an array to filter the time column.
Option Explicit
Sub reqwews()
Dim dict As Object, k As Long, sr As Variant
Dim str As String, tmp As Variant
Dim sdt As Long, stm As Double, tm As Double, mns As Long
Set dict = CreateObject("scripting.dictionary")
dict.CompareMode = vbBinaryCompare
With Worksheets("sheet12")
sdt = .Cells(9, "E").Value2
stm = .Cells(9, "F").Value2
mns = .Cells(9, "G").Value2
sr = Application.Match(Format(sdt, "yyyy-mm-dd\T") & Chr(42), .Columns("A"), 0)
If IsError(sr) Then Exit Sub
For k = sr To .Cells(.Rows.Count, "A").End(xlUp).Row
str = .Cells(k, "A").Value2
If DateValue(CStr(Split(str, Chr(84))(0))) = sdt Then
tm = TimeValue(Left(Split(str, Chr(84))(1), 8))
If tm >= stm And tm < (stm + TimeSerial(0, mns, 0)) Then
dict.Item(str) = DateValue(CStr(Split(str, Chr(84))(0))) + _
TimeValue(Left(Split(str, Chr(84))(1), 8))
ElseIf tm >= (stm + TimeSerial(0, mns, 0)) Then
'if the datetimes are in ascending order there is no point in going further
Exit For
End If
ElseIf DateValue(CStr(Split(str, Chr(84))(0))) > sdt Then
'if the datetimes are in ascending order there is no point in going further
Exit For
End If
Next k
If CBool(dict.Count) Then
If .AutoFilterMode Then .AutoFilterMode = False
With .Cells(1, "A").CurrentRegion
.AutoFilter field:=1, Criteria1:=dict.keys, Operator:=xlFilterValues
With .Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0)
If CBool(Application.Subtotal(103, .Cells)) Then
'do something with filtered cells
.SpecialCells(xlCellTypeVisible).Select
End If
End With
End With
'If .AutoFilterMode Then .AutoFilterMode = False
End If
End With
End Sub
¹ All the code needed to parse your strings-that-look-like-datetimes to actual datetimes in in the above. I just haven't written the real datetimes back to the worksheet.
My code works below works but I'd like to add one function. I've got a large data sheet with each line repeated three times. Within each set of three I've added a month twice. The purpose is to smooth out forecasted sales into one month and two months beyond the estimated shipping date. Now I'd like to multiply my the values in column E by factors into column F. The original line in each set of three will =50%*E:E in column F, the second line will have =30%*E:E in column F, and the third line will have =20%*E:E in Column F. This process should be repeated continually for every set of three lines. Problem: My current code does give me the correct value, however the values are two cells lower than they need to be. Thanks for any help in advance! My current code is below:
Public Sub DateAdd()
Dim r As Long
Dim l As Long
Dim Quant As Long
Dim dttTemp As Date
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("SalesForce Projects")
Application.ScreenUpdating = False
For r = ws.Range("A" & ws.Rows.Count).End(xlUp).Row To 1 Step -1
With ws.Cells(r, 1).EntireRow
.Copy
.Resize(2).Offset(1, 0).Insert Shift:=xlDown
End With
dttTemp = ws.Cells(r, "S").Value
ws.Cells(r + 1, "S").Value = DateSerial(Year(dttTemp), Month(dttTemp) + 1,
Day(dttTemp))
ws.Cells(r + 2, "S").Value = DateSerial(Year(dttTemp), Month(dttTemp) + 2,
Day(dttTemp))
Next r
Application.ScreenUpdating = True
' This is where my code is bad
For l = ws.Range("A" & ws.Rows.Count).End(xlUp).Row To 1 Step -3
Quant = ws.Cells(l, "E").Value
ws.Cells(l, "F").Value = Cells(l, "E") * 0.5
ws.Cells(l + 1, "F").Value = Cells(l, "E") * 0.3
ws.Cells(l + 2, "F").Value = Cells(l, "E") * 0.2
Next l
End Sub
Why not do it in the first loop like below?
Public Sub DateAdd()
Dim r As Long
Dim l As Long
Dim Quant As Long
Dim dttTemp As Date
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("SalesForce Projects")
Application.ScreenUpdating = False
For r = ws.Range("A" & ws.Rows.Count).End(xlUp).Row To 1 Step -1
With ws.Cells(r, 1).EntireRow
.Copy
.Resize(2).Offset(1, 0).Insert Shift:=xlDown
End With
dttTemp = ws.Cells(r, "S").Value
ws.Cells(r, "F").Value = Cells(r, "E") * 0.5 '\\ First line
ws.Cells(r + 1, "S").Value = DateSerial(Year(dttTemp), Month(dttTemp) + 1, Day(dttTemp))
ws.Cells(r + 1, "F").Value = Cells(r, "E") * 0.3 '\\ Second line
ws.Cells(r + 2, "S").Value = DateSerial(Year(dttTemp), Month(dttTemp) + 2, Day(dttTemp))
ws.Cells(r + 2, "F").Value = Cells(r, "E") * 0.2 '\\ Third line
Next r
Application.ScreenUpdating = True
End Sub
When you say "50% of the value in column E," you could mean the entire value of all 90 in column E or just the value of the three cells in a set. If you mean the first then (I assume that row 1 is headings, so your values start at row 2.) In cell F2 enter the formula
=Sum(E:E)*.5
In cell F3 enter
=SUM(E:E)*.3
In cell F4 enter
=SUM(E:E)*.2
If you mean the other option then enter:
In F2 =Sum(E2:E4)*.5
in F3 =Sum(E2:E4)*.3
In F4 =Sum(E2:e4)*.2
Now select f2:f4. Place your mouse on the bottom right corner and you should see the cursor change to a small black cross. Double-click and the formulas will be replicated down the sheet. If you have more than one sheet to fill then control click on the tab names before starting this process to similtainoiusly copy to all selected sheets.
In this case there is no need to loop backwards. Update the For statement to the following:
For l = 1 to ws.Range("A" & ws.Rows.Count).End(xlUp).Row Step 3
Then it should produce desired results.
I have dates along with time under Col K and certain values (numbers) corresponding to these days under Col M.
I have a code that changes the color of these values if they are greater than 1 and if they have a text "waiting" in col P.
What I don't know to do is, add the below condition into this code:
1.I want to identify if these days belongs to a Sunday.
2.If Yes, then I want to check if the Sunday hours (lets say the date/time format is "15/1/2016 17:00" so the remaining time left for Sunday to get over is 0.3 day) subtracted from the number in Col M and if still the number is >1, then it should be highlighted in "Red".
3.The subtraction should not affect or appear in the current sheet.
I tried the below code but I'm not sure where I'm making the mistake as there are no result.
Sub Datefilter()
Dim r As Long
Dim m As Long
On Error GoTo ExitHere:
m = Range("M:P").Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
Application.ScreenUpdating = False
For r = 1 To m
remainingDay = 0
If Weekday(Range("K" & r)) = 1 Then
remainingDay = Round((24 - Format(TimeValue(Range("K" & r)), "h")) / 24, 1)
End If
If Range("P" & r) = "*waiting*" Then
If Range("M" & r) - remainingDay >= 1 Then
Range("M" & r).Cells.Font.ColorIndex = 3
Else
Range("M" & r).Cells.Font.ColorIndex = 0
End If
End If
Next r
ExitHere:
Application.ScreenUpdating = True
End Sub
I feel this would be much easier with Excel's built-in functions and some helper columns.
(1) Use the WEEKDAY() function to get the day of the week. Then use a simple comparison to check if it is Sunday.
(2) Dates are stored as the amount of time expired since 0th January 1900, with partial dates as fractions. Therefore, to return the time, simply take the rounded bit of the date from the date: =A1-ROUNDDOWN(A1,0)
(3) Use conditional formatting to check if the cell is < 1 and then turn it red.
Let me know if you would like a screenshot of an example.
Try this:
Sub Datefilter()
Dim r, lastrow, remainingDay As Long
'On Error GoTo ExitHere: ' I recommend to delete this
lastrow = Range("M:P").Cells(Rows.Count, "A").End(xlUp).Row
Application.ScreenUpdating = False
For r = 1 To lastrow
remainingDay = 0
If Weekday(Range("K" & r).Value, vbSunday) = 1 Then
remainingDay = Round((24 - Format(TimeValue(Range("K" & r)), "h")) / 24, 1)
If InStr(1, Range("P" & r).Text, "waiting", vbTextCompare) > 0 Then
If Range("M" & r) - remainingDay >= 1 Then
Range("M" & r).Cells.Font.ColorIndex = 3
Else
Range("M" & r).Cells.Font.ColorIndex = 0
End If
End If
End If
Next r
'ExitHere: ' I recommend to delete this
Application.ScreenUpdating = True
End Sub
This is my code:
Dim RowLast As Long
Dim sunmLast As Long
Dim tempLast As Long
Dim filterCriteria As String
Dim perporig As Workbook
Dim x As String
tempLast = ThisWorkbook.Sheets("combine BOMs").Cells(Rows.Count, "E").End(xlUp).Row
Range("D5:G" & tempLast).ClearContents
Range("G5:G" & tempLast).Interior.ColorIndex = 0
tempLast = ThisWorkbook.Sheets("combine BOMs").Cells(Rows.Count, "A").End(xlUp).Row
Range("A5:A" & tempLast).ClearContents
tempLast = ThisWorkbook.Sheets("combine BOMs").Cells(Rows.Count, "B").End(xlUp).Row
'Perpetual
Set perporig = Workbooks.Open("\\Etnfps02\vol1\DATA\Inventory\Daily tracking\perpetual.xlsx", UpdateLinks:=False, ReadOnly:=True)
RowLast = perporig.Sheets("perpetual").Cells(Rows.Count, "A").End(xlUp).Row
perporig.Sheets("perpetual").Cells(3, 1) = "Part Number"
For i = 5 To tempLast
Cells(i, 1) = i - 4
perporig.Sheets("perpetual").AutoFilterMode = False
filterCriteria = ThisWorkbook.Sheets("combine BOMs").Range("B" & i).Value
perporig.Sheets("perpetual").Range("A3:J" & RowLast).AutoFilter Field:=1, Criteria1:=filterCriteria
Counter = perporig.Sheets("perpetual").Cells(RowLast + 1, 1).End(xlUp).Row
If Counter = 3 Then
Cells(i, 5).Value = "Not on perpetual"
Else
ThisWorkbook.Sheets("combine BOMs").Cells(i, 5).Value = WorksheetFunction.Sum(perporig.Sheets("perpetual").Range("H4:H" & RowLast).SpecialCells(xlCellTypeVisible))
x = perporig.Sheets("perpetual").Cells(Cells(RowLast + 1, 1).End(xlUp).Row, 4).Value
MsgBox x, vbOKOnly, perporig.Sheets("perpetual").Cells(RowLast + 1, 1).End(xlUp).Row
ThisWorkbook.Sheets("combine BOMs").Cells(i, 4).Value = x
End If
perporig.Sheets("perpetual").AutoFilterMode = False
Next
perporig.Close savechanges:=False
This is the file from which I am clicking my button (or ThisWorkbook)
This is the perpetual file when it is running on the last row of data:
Notice the difference in D9280: it shows stocking type as "P" in the perpetual file, but "B" in my final result, which comes up in cell D12 in ThisWorkbook. To debug, I created a Msgbox prompt for everytime it gets that value for all rows. For every other row, it gives the correct value ("P"), but for this one, msgbox shows "B". The title of the msgbox is the row number, which shows it is taking the correct row whilr getting the value, just that I don't know why it is taking wrong value. I have tried for different data sources, it seems to be coming up with "B" in wrong places every so often.
In the code, just above the line, I have the line to get the on hand quantity, which it does take correctly (I used xltypevisible to paste values for this field, but that is only because I wanted a sum of the results and this was the only way I knew). It's only this stocking type column which shows wrong values randomly.
Any ideas?
Thanks!
1)
Cells(i, 1) = i - 4
as it is written , it refers to perporig.Cells(i, 1)
is this what you want?
2)
perporig.Sheets("perpetual").Range("A3:J" & RowLast).AutoFilter Field:=1, Criteria1:=filterCriteria
would filter from row 3, while you have headers in row 4 and data from row 5 downwards
change it to
perporig.Sheets("perpetual").Range("A4:J" & RowLast).AutoFilter Field:=1, Criteria1:=filterCriteria
3)
what do you think is Counter doing? Not certainly count visible rows only
Credits to findwindow, I found the answer. The .cells(cells()) part didn't have the correct sheet reference for the inner cells():
Instead of
x = perporig.Sheets("perpetual").Cells(Cells(RowLast + 1, 1).End(xlUp).Row, 4).Value
MsgBox x, vbOKOnly, perporig.Sheets("perpetual").Cells(RowLast + 1, 1).End(xlUp).Row
I used this:
With perporig.Sheets("perpetual")
x = .Cells(.Cells(RowLast + 1, 1).End(xlUp).Row, 4).Value
MsgBox x, vbOKOnly, .Cells(RowLast + 1, 1).End(xlUp).Row
End With
And it worked.
Thanks for your help!