Show a msgbox with missing dates where user has not enterred info - excel

Im pretty new to vba and would like some advice
I have a timesheet spreadsheet where a user enters the amount of time it takes for them to complete tasks on a daily basis. Column A indicates the user and column B the date, then column c to x are the different tasks. The data is inputted on a form on another sheet and then a macro adds the data to my sheet and shows a messagebox confirming their hours have been enterred and the date for - I would like this message box to also show any dates (earlier than todays date) where the selected user (named within a cell on the sheet) has not enterred any hours within the current year?
Sub Macro12()
'
' Macro12 Macro
' Macro recorded 01/11/2013 by christopher.hodges
'
'
If Range("C13") = "" Then
MsgBox ("Please Select Department")
Exit Sub
End If
If Range("C14") = "" Then
MsgBox ("Please Select Employee")
Exit Sub
End If
If Range("C15") = "" Then
MsgBox ("Please Enter Date")
Exit Sub
End If
If Sheets("Form").Range("J39").Value < 7.5 Then
MSG1 = MsgBox("Hours are less than 7.5, do you wish to add?", vbYesNo, "Hours Less than 7.5")
If MSG1 = vbNo Then
Exit Sub
End If
End If
Range("E13:E35").Copy
Range("C16").PasteSpecial
Range("G13:G38").Copy
Range("C39").PasteSpecial
Range("I13:I31").Copy
Range("C65").PasteSpecial
Sheets("Data").Select
Call ShowAllRecords
Sheets("Form").Range("C13:C84").Copy
Sheets("Data").Range("A2").End(xlDown).Offset(1, 0).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=True
Sheets("Data").Rows("3:3").Copy
Sheets("Data").Rows("3:3").Select
Selection.End(xlDown).PasteSpecial Paste:=xlPasteFormats, Operation:=xlNone, _
SkipBlanks:=False, Transpose:=False
ActiveSheet.Cells(ActiveCell.Row, 1).Select
Sheets("Form").Select
Range("B16").Copy Range("C16:C83")
Range("C13:C15,E13:E35,G13:G38,I13:I32").ClearContents
Range("C15") = "=today()"
Range("A1").Select
MsgBox ("Hours for " & Range("C15").Value & " Added")
End Sub

I have only tested this on a small data set. Know that if you data set is very large this might not be the best way to go (although if it is very large a DB would be better anyway). but you can call like so.
Sub missedWork(employee_name AS String)
Dim missedDates As String
missedDates = missingDates(employee_name,earliestDate(employee_name))
If missedDates <> "" Then
msgbox "You did not enter hours for the following days: " & missedDates
End If
End Sub
Function earliestDate(emp As String) As Date
Dim e_date AS Date
Dim lcell As Range
e_date = Date()
For Each lcell in Range("$A$2","$A$" & Cells(Rows.Count, 1).End(xlUp).Row)
If lcell.Value = emp Then
If Cells(lcell.Row,"B") < e_date And Year(Cells(lcell.Row,"B")) = Year(Date) then
e_date = Cells(lcell.Row,"B")
End If
End If
Next lcell
earliestDate = e_date
End Function
Function missingDates(emp AS String, e_date As Date) AS String
Dim lcell As Range
Dim msg As String
Dim c_date As Date
msg = ""
c_date = e_date
While c_date < Date()
If WeekDayName(WeekDay(c_date)) <> "Saturday" AND WeekDayName(WeekDay(c_date)) <> "Sunday" Then
If Not(workedDate(emp,c_date)) Then
msg = msg & vbNewLine & Format(c_date,"mm/dd/yyyy")
End If
End If
c_date = DateAdd("d",1,c_date)
Wend
missingDates = msg
End Function
Function workedDate(emp AS String, c_date As Date) AS Boolean
Dim lcell As Range
For Each lcell in Range("$A$2","$A$" & Cells(Rows.Count, 1).End(xlUp).Row)
If lcell.Value = emp Then
if Cells(lcell.Row,"B") = c_date Then
workedDate = True
Exit For
End If
End If
Next lcell
End Function

Related

Add another filter criteria

How do I add another filter criteria?
So that I can filter by date (like it does) and if comboBox1 value = to what is in column A for each row
The other one I have is filter by date (like it does) and if there is a value in column H for each row
Private Sub CommandButton1_Click()
Dim strStart As String, strEnd As String, strPromptMessage As String
If TextBox1.Value = "" Then
TextBox1.Value = Date
End If
If TextBox2.Value = "" Then
TextBox2.Value = Date
End If
'Prompt the user to input the start date
strStart = TextBox1.Value
'Validate the input string
If Not IsDate(strStart) Then
strPromptMessage = "Oops! It looks like your entry is not a valid " & _
"date. Please retry with a valid date..."
MsgBox strPromptMessage
Exit Sub
End If
'Prompt the user to input the end date
strEnd = TextBox2.Value
'Validate the input string
If Not IsDate(strStart) Then
strPromptMessage = "Oops! It looks like your entry is not a valid " & _
"date. Please retry with a valid date..."
MsgBox strPromptMessage
Exit Sub
End If
'Call the next subroutine, which will do produce the output workbook
Call CreateSubsetWorksheet(strStart, strEnd)
Unload Me
End Sub
Public Sub CreateSubsetWorksheet(StartDate As String, EndDate As String)
Dim wksData As Worksheet, wksTarget As Worksheet
Dim lngLastRow As Long, lngLastCol As Long, lngDateCol As Long
Dim rngFull As Range, rngResult As Range, rngTarget As Range
'Set references up-front
Set wksData = ThisWorkbook.Worksheets("CopyDatabase")
lngDateCol = 5 '<~ we know dates are in column E
'Identify the full data range on Sheet1 (our data sheet) by finding
'the last row and last column
lngLastRow = LastOccupiedRowNum(wksData) '<~ straight from VBA Toolbelt!
'lngLastRow = Cells(Rows.Count, 1).End(xlUp).Row
lngLastCol = LastOccupiedColNum(wksData) '<~ straight from VBA Toolbelt!
'lngLastCol = Cells(1, Columns.Count).End(xlToLeft).Column
With wksData
Set rngFull = .Range(.Cells(3, 1), .Cells(lngLastRow, lngLastCol))
End With
'Apply a filter to the full range we just assigned to get rows
'that are in-between the start and end dates
With rngFull
.AutoFilter Field:=lngDateCol, _
Criteria1:=">=" & StartDate, _
Criteria2:="<=" & EndDate
'If the resulting range contains only 1 row, that means we filtered
'everything out! Check for this situation, catch it and exit
If wksData.AutoFilter.Range.Columns(1).SpecialCells(xlCellTypeVisible).Count = 1 Then
MsgBox "Oops! Those dates filter out all data!"
'Clear the autofilter safely and exit sub
wksData.AutoFilterMode = False
If wksData.FilterMode = True Then
wksData.ShowAllData
End If
Exit Sub
Else '<~ otherwise we're all good!
'Assign ONLY the visible cells, which are in the
'date range specified
Set rngResult = .SpecialCells(xlCellTypeVisible)
'clear contents
ThisWorkbook.Sheets("Reports").Range("A3:A" & Range("A3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("B3:B" & Range("B3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("C3:C" & Range("C3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("D3:D" & Range("D3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("E3:E" & Range("E3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("F3:F" & Range("F3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("G3:G" & Range("G3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("H3:H" & Range("H3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("I3:I" & Range("I3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("J3:J" & Range("J3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("K3:K" & Range("K3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("L3:L" & Range("L3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("M3:M" & Range("M3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("N3:N" & Range("N3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("O3:O" & Range("O3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("P3:P" & Range("P3").End(xlDown).Row).ClearContents
ThisWorkbook.Sheets("Reports").Range("Q3:Q" & Range("Q3").End(xlDown).Row).ClearContents
'Create a new Worksheet to copy our data to and set up
'a target Range (for super easy copy / paste)
Set wksTarget = ThisWorkbook.Sheets("Reports")
Set rngTarget = wksTarget.Cells(2, 1)
rngResult.Copy Destination:=rngTarget
End If
End With
'Clear the autofilter safely
wksData.AutoFilterMode = False
If wksData.FilterMode = True Then
wksData.ShowAllData
End If
'Holler at the user, our macro is done!
MsgBox "Data transferred!"
End Sub

How to run through columns and rows of a table in excel with vba

I am currently working on writing a data verification makro. Currently, it runs through one column and throws an error if the wrong data type is entered. The columns are dynamic because there will be new entries.
How do I run this code through several columns not only one?
Sub checken()
Dim i As Integer
Range("D4").Select
Do Until IsEmpty(ActiveCell)
If IsNumeric(ActiveCell) = False Then
MsgBox ("A number has to be entered " & "row " & ActiveCell.Row)
End If
ActiveCell.Offset(1, 0).Select
Loop
End Sub
You can try below sub-
Sub CheckColumns()
Dim rng As Range
Dim lCol As Long, lRow As Long
lCol = Range("D4").End(xlToRight).Column
lRow = Range("D4").End(xlDown).Row
For Each rng In Range("D4", Cells(lRow, lCol))
If IsNumeric(rng) = False Then
MsgBox ("A number has to be entered " & "row " & rng.Row)
End If
Next rng
End Sub

VBA No Cells are found [duplicate]

This question already has answers here:
Handle "No cells were found" error when filtered range is empty
(4 answers)
Closed 9 months ago.
I used this yesterday and it ran fine but today I got a error "Run-time error '1004': No cells were found.
It bugs at
Range("A6:A30").SpecialCells(xlCellTypeVisible).Find("Temp").Select
Attached Macro Below
Sub HrsInput()
' Disable screen updating.
Application.ScreenUpdating = False
Application.DisplayAlerts = False
' Dim workbooks and sheet names.
Dim WB1, WB2 As Workbook, Year As String
Set WB1 = ActiveWorkbook
Year = Mid(ActiveSheet.Name, 10, 4)
' Copy-n-paste raw reports.
Dim FSO As Object, SourcePath As String, DestinPath As String
Set FSO = CreateObject("Scripting.FileSystemObject")
SourcePath = "\\ONTWSFS003\share\MIRALOMA\Brian\Raw Reports (FM)\*.xls"
DestinPath = "\\ONTWSFS003\share\MIRALOMA\Brian\"
FSO.CopyFile SourcePath, DestinPath
' Repeat below process until encountering an error.
Dim FileCount As Integer
Filename = Dir(SourcePath)
Do While Filename <> ""
FileCount = FileCount + 1
Filename = Dir()
Loop
For FileNum = 1 To FileCount
' Open raw report.
Workbooks.Open Filename:= _
"\\ONTWSFS003\share\MIRALOMA\Brian\*.xls"
' Capture raw report and total hours.
Set WB2 = ActiveWorkbook
Dim TotalOT As Double, BUNum As String, ReportDate() As String, WeekNum As Integer, ColNum As Integer
BUNum = Left(Range("A5"), 7)
ReportDate = Split(Range("A7"), " ")
WeekNum = WorksheetFunction.WeekNum(ReportDate(4))
Range("A:Q").UnMerge
' If not OT then skip the file.
If Not Range("A14:Z14").Find("OT1.5") Is Nothing Then
Range("A14:Z14").Find("OT1.5").Select
ColNum = Selection.Column
Range("A15:A300").Find("total").Select
Selection.Offset(0, ColNum - 1).Select
TotalOT = Selection.Value
' Fill out job title if empty.
Dim EmptyJobRng As Range, EmptyJobCell As Range
Set EmptyJobRng = Range("C15:C150").SpecialCells(xlCellTypeBlanks)
For Each EmptyJobCell In EmptyJobRng.Cells
If EmptyJobCell.Offset(0, 2) <> "" Then
EmptyJobCell = EmptyJobCell.Offset(-1, 0)
End If
Next EmptyJobCell
' Filter by temp only.
If Not Range("C15:C100").Find("*") Is Nothing Then
With Range("C14:Y150")
.AutoFilter field:=3, Criteria1:="<>"
.AutoFilter field:=1, Criteria1:="*Temp"
End With
End If
' Calculate total temp OT hours.
Dim TotalTempOT As Double, OT As Range
TotalTempOT = 0
Range("A14:Z14").Find("OT1.5").Select
Selection.Offset(1, 0).Select
Selection.Resize(150, 1).Select
Set OT = Selection.SpecialCells(xlCellTypeVisible)
For Each TempOT In OT.Cells
TotalTempOT = TotalTempOT + TempOT
Next TempOT
' Filter by BU and blank rows.
WB1.Activate
With Range("A5:BD30")
.AutoFilter field:=2, Criteria1:=BUNum
.AutoFilter field:=WeekNum + 2, Criteria1:="="
End With
' Locate temp row and week column to paste total temp OT hours.
Range("A6:A30").SpecialCells(xlCellTypeVisible).Find("Temp").Select
Selection.Offset(0, WeekNum + 1).Select
Selection = TotalTempOT
' Locate CEVA row and week column to paste total CEVA OT hours (total OT - total temp OT).
Range("A6:A109").SpecialCells(xlCellTypeVisible).Find("CEVA").Select
Selection.Offset(0, WeekNum + 1).Select
Selection = TotalOT - TotalTempOT
' Clear filters.
Sheets("Tracking " & Year & " (by BU)").ShowAllData
End If
' Delete current raw report.
WB2.Activate
ActiveWorkbook.Saved = True
ActiveWorkbook.ChangeFileAccess xlReadOnly
Kill ActiveWorkbook.FullName
WB2.Close
WB1.Activate
Next FileNum
' Update week number and weekly total OT hours.
' Week number
Range("A4").Offset(0, WeekNum).Select
Selection.Copy
Selection.Offset(0, 1).Select
Selection.PasteSpecial (xlPasteFormulas)
' Report date
Range("A5").Offset(0, WeekNum + 1).Select
Selection = "WE" & ReportDate(4)
' Weekly total OT hours
Range("A110").Offset(0, WeekNum).Select
Selection.Copy
Selection.Offset(0, 1).Select
Selection.PasteSpecial (xlPasteFormulas)
' Format Painter to new column
Range("B:B").Select
Selection.Offset(0, WeekNum - 1).Select
Selection.Copy
Selection.Offset(0, 1).Select
Selection.PasteSpecial (xlPasteFormats)
Sheets("Tracking " & Year & " (by Loc)").Select
Range("A:A").Select
Selection.Offset(0, WeekNum - 1).Select
Selection.Copy
Selection.Offset(0, 1).Select
Selection.PasteSpecial (xlPasteFormats)
' Notification when complete.
MsgBox "Data imported successfully.", vbOKOnly, "Complete"
' Enable screen updating.
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
SpecialCells(xlCellTypeVisible) raises a run-time error if there are no visible cells - one option is to ignore that error:
Dim f As range
'...
Set f = Nothing
On Error Resume Next 'ignore error if no visible cells
Set f = Range("A6:A30").SpecialCells(xlCellTypeVisible).Find("Temp")
On Error Goto 0 'stop ignoring errors
If Not f Is Nothing then
'do something with f
Else
'No visible cells, or no visible "Temp" cell...
End If
'...

Excel VBA Timeline slicerChache doesnt work with data from power query

I have a code where Pivot timeline date is changing based on the date.
Previously I had an sheet with data, but recently change the data source to from power query.
My error is that Timeline slicer doesn't work anymore.
Does anyone know why this error can occure?
ERROR : Run-time error '5' :
Invalid procedure call or argument.
Sub Datos_nustatymas()
Dim wb As Workbook, ws As Worksheet
Dim Lastrow As Long, i As Long, r As Long
Dim dt As Date, dtLast As Date, newdays As Long
Application.ScreenUpdating = False
Application.EnableEvents = False
Set wb = ThisWorkbook
wb.RefreshAll ' Refresh Pivot '
Set ws = wb.Sheets("Report")
With ws
' find end of existing data in B
Lastrow = .Cells(.Rows.Count, "B").End(xlUp).Row
' calc number of days to yesterday
dtLast = .Range("A" & Lastrow).Value2
newdays = Date - 1 - dtLast
If newdays < 1 Then
MsgBox "Report is up to date", vbExclamation
Exit Sub
Else
' extend column A to yesterday
With .Range("A" & Lastrow + 1).Resize(newdays)
.Formula = "=R[-1]C+1"
.Value = .Value
End With
End If
'update column B
For i = 1 To newdays
r = Lastrow + i
dt = .Cells(r, "A")
' this code selects a timeline date
ActiveWorkbook.SlicerCaches("NativeTimeline_VALUE_DATE").TimelineState. _
SetFilterDateRange dt, dt
' Copy/Paste details from Pivot to celected cells'
.Range("O4:Z4").Copy
.Cells(r, "B").PasteSpecial Paste:=xlPasteValuesAndNumberFormats, _
Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Next
End With
Application.ScreenUpdating = True
Application.EnableEvents = True
MsgBox newdays & " days added", vbInformation
End Sub```
Fixed. Just changed "NativeTimeline_VALUE_DATE" to "Timeline_VALUE_DATE" and it worked.

Selecting a Cell based on Row and Column Headers, and Inputting a Value From an Input Section on that Sheet

I've created a Table from the range A112:H206, with days of the week (sunday, monday, etc) heading the table row from B112-H112. In column A, I have names of individuals listed going all the way down to A206.
I have an input section at the top of the spreadsheet, where a user will select a name from a drop down menu in cell A109, a day of the week from a drop down menu in cell B2, and finally a value in cell C109 which should be inputted in the corresponding cell in the table.
I created a button named "Enter" to which upon clicking should search for the corresponding cell based on the input section above, and input the C109 Value in that cell. Unfortunately my attempts using VBA were unsuccessful! Any help would be greatly appreciated.
Thank you!
Private Sub CommandButton1_Click()
Dim ws1 As Worksheet
Dim x As Range
Dim y As Range
Dim valX, valY
Set ws1 = Sheets("Sheet1")
valX = ws1.Range("B2").Value
Set x = ws1.Range("A112:H112").Find(What:=valX, LookIn:=xlValues, _
lookat:=xlWhole)
If x Is Nothing Then
MsgBox "'" & valX & "' not found on '" & ws1.Name & "' !"
Exit Sub
End If
valY = ws1.Range("A109").Value
Set y = ws1.Range("A112:A206").Find(What:=valY, LookIn:=xlValues, _
lookat:=xlWhole)
If Not y Is Nothing Then
Range("C109").Select
Selection.Copy
ws1.Cells(x.Column, y.Row).Select
ActiveSheet.Paste
Range("C109").Select
Selection.ClearContents
Exit Sub
End If
End Sub
A friend of mine helped, I wanted to post it here just for reference for others!
Range("C109").Select
Selection.Copy
Dim Day As String
Dim Name As String
Dim nameFound As Boolean
Dim dayFound As Boolean
Name = Cells(109, "A").Value
Day = Cells(2, "B").Value
Range("A113").Select
nameFound = False
Do Until IsEmpty(ActiveCell)
If ActiveCell.Value = Name Then
nameFound = True
Exit Do
End If
ActiveCell.Offset(1, 0).Select
Loop
If nameFound = True Then
Dim nameAddress As Integer
nameAddress = ActiveCell.Row
Else
MsgBox "Name not found"
End If
Range("B112").Select
dayFound = False
Do Until IsEmpty(ActiveCell)
If ActiveCell.Value = Day Then
dayFound = True
Exit Do
End If
ActiveCell.Offset(0, 1).Select
Loop
If dayFound = True Then
Dim dayAddress As Integer
dayAddress = ActiveCell.Column
Else
MsgBox "Day not found"
End If
Cells(nameAddress, dayAddress).Select
ActiveSheet.Paste
If ActiveCell.Column = 2 Or ActiveCell.Column = 4 Or ActiveCell.Column = 6 Or ActiveCell.Column = 8 Then
ActiveCell.Interior.Color = RGB(83, 142, 213)
ElseIf ActiveCell.Column = 3 Or ActiveCell.Column = 5 Or ActiveCell.Column = 7 Then
ActiveCell.Interior.Color = RGB(182, 221, 232)
End If
Range("C109").Select
Selection.ClearContents
Untested:
Private Sub CommandButton1_Click()
Dim ws1 As Worksheet
Dim x As Range
Dim y As Range
Dim valX, valY
Set ws1 = Sheets("Sheet1")
valX = ws1.Range("A109").Value
Set x = ws1.Range("A112:H112").Find(What:=valX, LookIn:=xlValues, _
lookat:=xlWhole)
If x Is Nothing Then
MsgBox "'" & valX & "' not found on '" & ws1.Name & "' !"
Exit Sub
End If
valY = ws1.Range("B2").Value
Set y = ws1.Range("A112:A206").Find(What:=valY,LookIn:=xlValues, _
lookat:=xlWhole)
If Not y Is Nothing Then
With ws1.Range("C109")
.Copy ws1.Cells(y.Row, x.Column)' <<EDITED
.ClearContents
End With
Else
MsgBox "Name '" & valY & "' not found on '" & ws1.Name & "' !"
End If
End Sub

Resources