Excel: Enter dates in specific column - vba

My requirement is:
I want to enter date from 1st Jan to 31st Jan in columns E5 to AI5. Currently using the below code which is not working.
Secondly year i m taking as user input which should change every time.
Sub LoopA()
Call Using_InputBox_Method
Dim i As Integer
Dim j As Integer
Dim PH As Integer
i = 5
For j = 5 To 35
Cells(i, j).Value = "=Date(E1,1,j)"
Next j
End Sub
Public Function Using_InputBox_Method() As Integer
Dim Response As Integer
' Run the Input Box.
Response = Application.InputBox("Enter a Year.", _
"Number Entry", , 250, 75, "", , 1)
' Check to see if Cancel was pressed.
If Response <> False Then
' If not, write the number to the first cell in the first sheet.
Worksheets(1).Range("E1").Value = Response
End If
Using_InputBox_Method = Response
End Function

A)
Anything within " will be considered as a String. So "=Date(E1,1,j)" is just a string. What you want, I guess is
"=Date(E1,1," & j & ")"
B)
For j = 5 To 35
Are you sure you want to go up till 35? The max you can have in any month is 31 :)
Syntax of =Date() is DATE(year,month,day)
Also you would need an additional check here to see if it is a valid date. For example 30th Feb will give you an error.
C)
InputBox should be avoided to accept dates. It can generate errors. You may want to use THIS. If you still want to use InputBox then you will have to do validations to ensure that there are no errors.
D)
Regarding, the Year changing automatically, You will have to increment the Year in Column E once the user automatically enters the date.
Is this what you are trying?
Sub Sample()
Dim Yr As Long, i As Long
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Yr = Application.InputBox("Enter a Year.", _
"Number Entry", , 250, 75, "", , 1)
'~~> Set it to whatever Year Range you want
If Yr < 1900 Or Yr > 9999 Then
MsgBox "Incorrect Year"
Exit Sub
End If
With ws
.Range("E1").Value = Yr
For i = 5 To 35
.Cells(5, i).Formula = "=Date(E1,1," & (i - 4) & ")"
Next i
End With
End Sub

Related

Delete rows based on comparing cells to user entered date and skipping blank cells

I am looking for a way to remove rows based on the termination date of an employee. I don't want blank cells to be deleted because those employees are still active. I have a text box that pops up and asks for the dates and then show the entered date. Then it is supposed to search column G for any dates prior to the entered date and delete those rows, skipping any row that is blank.
I have been searching everywhere for a way to do this but I can't get the Macro to stop deleting every row but the headers. The dates are in column G and it's about 46 rows but that can change.
Sub DateSelectandClean()
'
' DateSelectandClean Macro
' User enters date and spreadsheet deletes everything prior to that date, ignoring empty cells.
Application.ScreenUpdating = False
Dim W2Year As Date, N As Long
Dim dt As Date
W2Year = CDate(Application.InputBox(Prompt:="Please enter W2 Year as xx/xx/xxxx Date:", Type:=2))
MsgBox W2Year
N = Cells(Rows.Count, "G").End(xlUp).Row
For i = N To 2 Step -1
dt = Cells(i, 1).Value
If (Cells(i, 1).Value <> "" And dt < W2Year) Then
Cells(i, 1).EntireRow.Delete
End If
Next i
Application.ScreenUpdating = True
End Sub
Sample Data
The main issue is you're checking the "A" column for your date info, and deleting based on that. If your dates are in "G", you should check Cells(x,7), not Cells(x,1).
Sub DateSelectandClean()
'
' DateSelectandClean Macro
' User enters date and spreadsheet deletes everything prior to that date, ignoring empty cells.
Application.ScreenUpdating = False
Dim W2Year As Date, lastRow As Long, i As Long, dateCol As Long
Dim dt As Date
dateCol = 7 ' for column G
Do While W2Year = "00:00:00"
W2Year = Format(Application.InputBox(Prompt:="Please enter W2 Year as xx/xx/xxxx Date:", Type:=2), "mm/dd/yyyy")
MsgBox W2Year
Loop
lastRow = Cells(Rows.Count, dateCol).End(xlUp).Row
For i = lastRow To 2 Step -1
'If Cells(i, dateCol).Value <> "" Then
If IsDate(Cells(i,dateCol)) Then
dt = CDate(Format(Cells(i, dateCol).Value, "mm/dd/yyyy"))
If dt <= W2Year Then
Cells(i, dateCol).EntireRow.Delete
End If
End If
Next i
Application.ScreenUpdating = True
End Sub
I also change the variables from Date to String which allows a little bit of error catching when the user inputs info. You can edit that back if you wish, I was just thinking of a time when someone puts in "wrong" or incorrectly formatted info.
Your code might be getting an issue in blank date.
I separate the IF so that it won't continue the validation on date.
e.g. IF "" < #01/01/2017#
Try this, not much changes though:
Sub DateSelectandClean()
' DateSelectandClean Macro
' User enters date and spreadsheet deletes everything prior to that date, ignoring empty cells.
Application.ScreenUpdating = False
Dim dateCol, iRow
Dim W2Year As Date, N As Long
Dim dt As String
W2Year = CDate(Application.InputBox(Prompt:="Please enter W2 Year as dd/mm/yyyy Date:", Type:=2))
MsgBox W2Year
N = Cells(Rows.Count, "G").End(xlUp).Row
dateCol = 7
For iRow = N To 2 Step -1
dt = Cells(iRow, dateCol).Value
If (Cells(iRow, dateCol).Value <> "") Then
If (CDate(dt) < CDate(W2Year)) Then
Cells(iRow, dateCol).EntireRow.Delete
End If
End If
Next
Application.ScreenUpdating = True
End Sub

Excel VBA - Conditional highlighting based on many criteria

I have a vba-created speadsheet with 4 sets of criteria. I need to highlight names at the bottom of the sheet based on whether or not they meet all the criteria.
I need the name to highlight if the analyst took 91 minutes or less of total break (B3:F9) each day, 15 minutes or less of tea break (B12:F18), and made at least 3 outbound calls each day (provided the staff time was 8 hours and 58 minutes or more (if it wasn't, the 3 call threshold does not apply)).
So, a function would be something like:
If
TtlB<91 mins & TeaB<15
& If
StfT <8:58:00 ignore ObC
Else If
StfT >8:58:00 & ObC>=3
Highlight (analyst name in A22:A28)
I know it will probably involve a nested loop or two, I just don't know where to get started. The loop for calculating "Total Minutes Owed" is below which can probably be modified to help me get started with this.
Dim i As Integer, j As Integer, k As Integer
j = 3
k = 12
For i = 22 To 28
Range("B" & i) = "=SUM(G" & j & ",G" & k & ")"
j = j + 1
k = k + 1
Next i
I'm pretty shure that a much more compact code can be done. But, since nobody answer you in the last four hours, try the following at least as an start.
Private Sub CommandButton1_Click()
Dim oWs As Worksheet
Dim rAnalysts As Range
Dim rBreak As Range
Dim rObC As Range
Dim rTea As Range
Dim rST As Range
Dim rRow As Range
Dim rIntersection As Range
Dim rCell As Range
Set oWs = Worksheets("MyData") 'The worksheet where data resides
MaxBreakTime = oWs.Cells(1, 7).Value 'The max break time. I set it in cell G1. Change according to your needs
Set rAnalysts = oWs.Rows("3:9") 'Define the rows for analysts
Set rBreak = oWs.Range("B:F") 'define the columns where Break data is placed
'(similarly, set ranges for tea break, etc)
For Each rRow In rAnalysts.Rows 'for each row in the analyst range
sAnalystName = oWs.Cells(rRow.Row, 1).Value 'get the name of the analyst
lBreakTime = 0 'restart this variable to zero
Set rIntersection = Application.Intersect(rRow, rBreak) ' intersect the row (the analyst) with the columns of the Break range
If rIntersection Is Nothing Then
MsgBox "Ranges do not intersect. Something is radically wrong."
Else
For Each rCell In rIntersection.Cells 'id est, friday through thursday
If rCell.Value > MaxBreakTime Then 'if break was longer that stipulated,....
lBreakTime = lBreakTime + rCell.Value - MaxBreakTime 'add the excess to the variable
End If
Next
End If
'write data somewhere (here, 30 rows down from original Analysts range)
oWs.Cells(rRow.Row + 30, 1) = sAnalystName
oWs.Cells(rRow.Row + 30, 2) = lBreakTime
If lBreakTime > 0 Then
oWs.Cells(rRow.Row + 30, 2).Font.Color = vbGreen
oWs.Cells(rRow.Row + 30, 2).Interior.Color = vbRed
End If
Next
'Here something similar for Tea break and Outbounds calls
'Since output is already writen, you can reuse variables like rIntersection or rCell
End Sub

Hide rows based on the date

I am trying to keep the last 365 days visible in a micro tracking worksheet. As a new date gets inputted it would hide the first visible entry on the sheet so that only 365 cells are constantly displayed with the newest date at the bottom(ex Jan 15, 2015) and the oldest date at the top(Jan 15, 2014). When the user inputs Jan 16, 2015 it would hide Jan 15, 2014 so that the first entry is now Jan 16, 2014, and so on.
It has probably been about 15 years since I last used VBA but currently the code shown below will hide row 3 (where the first date and data is entered) but after that I can't get it to then hide row 4 once row 369 has text entered. Some insight into what I might be doing wrong would be greatly appreciated.
I would also assume that as this sheet became progressively larger it would start to slow down in opening or running smoothly so I would have to start fresh unless there is a way to make sure it always stays fast.
Dim i As Integer
Dim j As Integer
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
i = 3
j = 368
If Cells(j, j) = "" Then
Rows(i).Hidden = True
End If
i = i + 1
j = j + 1
End Sub
This is a completely different approach, but might suit you better in the long run.
Instead of hiding the rows to view what you are interested in. This approach uses two sheets.
Log Sheet: Contains all days
Report Sheet: Re-fills with only the last 365 days.
Setup Involved:
Set a second sheet up for your report, and give it the same headers as your Log Sheet.
Place the code provided in a module
If you want, you can add a workbook event so when the workbook opens, you can call this sub and have it update itself, or attach it to a hotkey or button.
This gives you plenty of room to create new formulas and charts to work over the set range of the report sheet. You can hide the Log Sheet.
Code:
Sub lastYearReportFill()
Dim lastRow As Long, lastCol As Long, lRow As Long, rRow As Long
Dim log As String, report As String
Dim today As Date, tempDate As Date
Dim daysTest As Long
log = "Log" 'Name your worksheets here
report = "Report"
today = Now
lastRow = Sheets(log).Range("A" & rows.count).End(xlUp).row
lastCol = Sheets(log).Cells(2, Columns.count).End(xlToLeft).column 'Using Header Row
For lRow = 3 To lastRow
tempDate = Sheets(log).Cells(lRow, 1)
daysTest = DateDiff("d", tempDate , today)
If daysTest = 365 Then
Exit For
End If
Next lRow
For rRow = 3 To 368
For lCol = 1 To lastCol
Sheets(report).Cells(rRow, lCol).Value = Sheets(log).Cells(lRow, lCol).Value
Next lCol
lRow = lRow + 1
Next rRow
End Sub
This should do the trick:
Sub HideRows()
Dim lngLastRow As Long
lngLastRow = Sheets("Sheet1").Cells(1, 1).End(xlDown).Row
If lngLastRow < 365 Then End
Rows(lngLastRow - 365).Hidden = True
End Sub
This is assuming that:
you are working in a sheet named "Sheet1" (if not, change the name in line 3 of the code accordingly)
the dates are in column A and start in row 1 (even the hidden ones). If the dates are in a different column, then change the second number in the cells(1, 1) statement to the number of the row. And if the dates do not start in row 1, change the first number of the cells(1, 1) statement to the row number of the first date.
And if you want to keep the row for the day exactly one year ago (as in, keep 1-15-14 on 1-15-15), you may need to change 365 in line 5 of the code to 366. This code also assumes that all other rows besides the one that was visible yesterday but doesn't need to be today are already hidden.
If you are concerned with speed, use Range AutoFilter Method which I answered HERE.
Applying it to your case:
Private Sub UpdateVisibleDates(sh As Worksheet, drng As Range)
With sh
Dim latest As Date
latest = .Range("A:A").Find("*", .Range("A1"), , , , xlPrevious).Value2
.AutoFilterMode = False
drng.AutoFilter 1, ">" & (latest - 365), xlAnd, "<=" & latest, False
End With
End Sub
Then just call it in your Worksheet_Change Event.
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo halt
Application.EnableEvents = False
If Not Intersect(Target, Me.Range("A:A")) Is Nothing Then
Dim r As Range
Set r = Me.Range("A1:A" & Me.Range("A:A") _
.Find("*", Me.Range("A1"), , , , xlPrevious).Row)
UpdateVisibleDates Me, r
End If
forward:
Application.EnableEvents = True
Exit Sub
halt:
MsgBox "Error: " & Err.Number & vbCrLf & _
Err.Description, vbExclamation
Resume forward
End Sub
This is considering you have a complete date in Column A and your input doesn't skip dates.
But regardless, it will still hide dates not within the 365 date difference of the last entered date. HTH.

Excel VBA: add a blank cell below every output

I have a little problem with my VBA code. I use the code below to display every date in a date range. So if the date range is 3 Dec - 5 Dec, it will display 3 Dec in cell E10, 4 Dec in cell E11 and 5 Dec in cell E12. This works fine, however I need to add 4 blank cells below every date (so 3 Dec will be in cell E10, but the 4th of December will be shown in cell E15 etc).
Private Sub cmdOK_Click()
Dim RowCount As Long
Dim ctl As Control
' Check user input
If Me.SdPicker.Value = "" Then
MsgBox "Please enter an start date.", vbExclamation, "Start data error"
Me.SdPicker.SetFocus
Exit Sub
End If
If Me.EdPicker.Value = "" Then
MsgBox "Please enter the end date.", vbExclamation, "End date error"
Me.EdPicker.SetFocus
Exit Sub
End If
' Write data to worksheet
With Worksheets("Projection_Daily").Range("X1")
.Value = Me.SdPicker.Value
End With
With Worksheets("Projection_Daily").Range("Y1")
.Value = Me.EdPicker.Value
End With
' Close the form to open Output sheet and implement date range
Worksheets("Projection_Daily").Activate
Worksheets("Projection_Daily").Columns(5).ClearContents
Dim StartDate As Date
Dim EndDate As Date
Dim NoDays As Integer
StartDate = Worksheets("Projection_Daily").Range("X1").Value
EndDate = Worksheets("Projection_Daily").Range("Y1").Value
NoDays = EndDate - StartDate + 4
Worksheets("Projection_Daily").Range("E10").Value = StartDate
Worksheets("Projection_Daily").Range("E10").Resize(NoDays).DataSeries Rowcol:=xlColumns, Type:=xlChronological, Date:=xlDay, Step:=1, Stop:=EndDate, Trend:=False
Unload Me
End Sub
This is the code I currently use, I have tried to insert .Offset(4,0) to the code but with no luck. I hope you can help me with this.
Thanks!
Try using a Loop condition like this:
i = 1 'To loop through the no of days
j = 10 'To start from row no 10
For i = 1 To NoDays 'Nodays = Enddate-Startdate
Sheet1.Cells(j, 5).value = StartDate
StartDate = StartDate + 1
j = j + 5 'To add a gap of 4 blank rows
Next i

Excel VBA script for loop with dates

I am calculating the number of work hours (8am to 8pm) between the 2 given dates, excluding Weekends and Public holidays, but my code syntax is incorrect.
Sample data:
Start day: 17/06/2011 08:00:00 AM
End day: 19/06/2011 08:00:00 PM
Sub SLA_Days_Resolved_F()
Dim x As Integer
' Set numrows = number of rows of data.
NumRows = Range("F2", Range("F2").End(xlDown)).Rows.Count
Dim total As Integer 'to count the total hours
Dim st As String 'start date cell
Dim en As String 'end date cell
Dim destCell As String
Dim d As Date ' for the loop
total = 0
' Establish "For" loop to loop "numrows" number of times.
For x = 2 To NumRows + 1
st = "G" & CStr(x) 'reference to the cells
en = "D" & CStr(x)
'loop from start date to end date
For d = Date(Range(st)) To Date(Range(en))
'check if the current date is found is a Public holiday in the range or if a weekend
If ((Vlookup(d,lookups!$o$3:$p$26,2,false))=1) or (weekend(d))Then
'minus 8 to remove hours before 8am.
total = (total + Hour(d) + minutes(d) / 60) - 8
End If
Next
Next
End Sub
You are not assigning any values to variables st or en.
Date is not a function available in VBA. You will probably need to use DateSerial function. Here is a simple example of looping over dates which you should be able to modify.
Sub LoopDates()
Dim d As Date
'Loop the days beteween today and March 1, 2013.
For d = DateSerial(Year(Now), Month(Now), Day(Now)) To DateSerial(2013, 3, 1)
Debug.Print d 'Prints the "d" value in the immediate window.
Next
End Sub
Also, you can't just put worksheet formulae in VBA. This line is definitely wrong syntax for Vlookup, and Weekend is not a formula that I'm aware of (testing it seems to confirm it is not a valid call on worksheet or in VBA.
If ((Vlookup(d,lookups!$o$3:$p$26,2,false))=1) or (weekend(d))Then
Rewrite as:
If Application.WorksheetFunction.Vlookup(d,Sheets("lookups").Range("$o$3:$p$26"),2,false)=1 _
or Not Application.WorksheetFunction.Weekday(d) Then
ANOTHER EXAMPLE of a date loop where I have dimensioned the variables in what I believe to be a more efficient manner:
Sub Test()
Dim st As Range
Dim x As Integer
Dim stDate As Date
Dim enDate As Date
Dim d As Date
Dim numRows as Long
NumRows = Range("F2", Range("F2").End(xlDown)).Rows.Count
For x = 0 To NumRows-2
'SET YOUR VARIABLES HERE
' This may seem redundant or unnecessary for this case, but it makes structuring nested
' loops easier to work with, and then there are fewer places to make changes,
' if you need to make changes.
Set st = Range("G2").Offset(x, 0)
Set en = Range("D2").Offset(x, 0)
stDate = DateSerial(Year(st), Month(st), Day(st))
enDate = DateSerial(Year(en), Month(en), Day(en))
'Then, loop through the dates as necessary
For d = stDate To enDate
Debug.Print d
'Do your code here.
Next
Next
End Sub