Make judgement and give reminder based on date (failed) - excel

I am trying to judge whether today's date is later than any date specified in a column of a worksheet everytime the workbook is opened to decide whether will give user a reminder. I use debug.print to make sure the condition I set was correct but there was no reminder popped out everytime I open the file. Could anyone point out where did I make the mistake? Thanks.
I used cdbl to convert date to double and compare between today and the date in the column. If anyone of them is earlier than today it will give user a reminder.
Private Sub UserForm_Initialize()
Dim i As Integer
Dim cnt As Integer
Count = 0
With ThisWorkbook.Worksheets("Gun Inventory")
For i = 2 To .Cells(Rows.Count, "A").End(xlUp).row
If Int(CDbl(Date)) > Int(CDbl(.Cells(i, "J").Value)) Or Int(CDbl(Date)) = Int(CDbl(.Cells(i, "J").Value)) Then
.Cells(i, "I") = "Needs Test"
Count = Count + 1
Else: Exit Sub
End If
Next i
If Count <> 0 Then MsgBox "You have guns needs check ASAP. Please review 'gun inventory' tab to see which gun it is."
End With
End Sub
I expect there should be a reminder but there is nothing. Not even an error, which is weird.

If you want to execute that portion of code when the workbook is opened you should use:
Sub Auto_Open()
Insert code here
End Sub
Or use Workbook_Open() but you will have to add it in ThisWorkbook class.

Related

Open MsgBox if a date on birthday list matches today

Every time I try and execute my code it says "object required."
I want a MsgBox to open if one a date on my birthday list matches today.
The birthday list extends from b2 to b100 and I want to look through to find the birthday.
This is a piece of code I took from a YouTube video.
The MsgBox pops up every time I open the workbook.
Private Sub Workbook_Open()
Dim cl As Range
Set cl = ThisWorbook.Sheets("Birthdays").Range("B2:B100")
If IsDate(cl) Then
If Now >= cl Then
MsgBox "Somebody's had a birthday!"
End If
End If
End Sub
You are getting Object Required error because of a typo ThisWorbook should be ThisWorkbook
It is very normal to encounter such errors. So always use Option Explicit. I have covered it in To ‘Err’ is Human
So Can I have it added to my code automatically?
Yes you can. To have it added to all new files you create, simply select "Tools" -> "Options" in the VBE, and tick the "Require Variable Declaration" box.
Note: This will effect only new files that you create. You will need to add it yourself to existing files.
I basically just want my excel to create a msgbox when I open it, if one of the date on my birthday list matches today.
You can use Application.WorksheetFunction.CountIf to check if there is today's date in a range.
Sub Sample()
Dim ws As Worksheet
Dim rng As Range
Dim matchFound As Long
Set ws = ThisWorkbook.Sheets("Birthdays")
Set rng = ws.Range("B2:B100")
matchFound = Application.WorksheetFunction.CountIf(rng, Date)
If matchFound > 0 Then
MsgBox "Birthday Found"
Else
MsgBox "Birthday Not Found"
End If
End Sub
Screenshot
cl is a Range object representing 99 dalmatians cells, each encapsulating a Variant value.
The IsDate function is happy to take a Variant, but doesn't know what to do with 99 of them.
Because Range has a hidden default property, you can use it as if it were a value - but, especially for someone that's just beginning to learn VBA, it makes for confusing, implicit, "magic" code that says one thing, and does another.
If IsDate(cl.Value) Then
The implicit Range.Value member call here, yields a Variant representing the cell's value itself if the range represents only a single cell, otherwise (i.e. if the range is for more than one cell) it yields a Variant pointing to a 2D Variant array (in this case 99x1) that's holding every single value.
IsDate wants one value, so if we have 99 of them, we need a loop. But here's the thing: the last thing we want to do is iterate individual cells, get their Value, and verify that - because that would be very slow.
So instead, we grab that 2D Variant array, and iterate that.
If cl.Count = 1 Then
'single-cell range: not a 2D array
If Now >= cl.Value Then
MsgBox "Somebody's had a birthday on " & Format(cl.Value, "yyyy-mm-dd")
End If
Exit Sub
End If
Dim values As Variant
values = cl.Value
Dim currentRow As Long
For currentRow = LBound(values, 1) To UBound(values, 1)
Dim currentCol As Long
For currentCol = LBound(values, 2) To UBound(values, 2)
Dim currentValue As Variant
currentValue = values(currentRow, currentCol)
If IsDate(currentValue) Then
If Now >= currentValue Then
MsgBox "Somebody's had a birthday on " & Format(currentValue, "yyyy-mm-dd")
Exit Sub
End If
End If
Next
Next
Right now the msgbox just pops up every time I open the excel whether a birthday matches or not.
Sounds like your actual code has On Error Resume Next somewhere - that makes VBA ignore any run-time errors and merrily keep running, ...and you definitely don't want that. Rule of thumb, never use On Error Resume Next to side-step an error. Execution is normally halted when there's an "object required" error: an unconditional MsgBox popping means execution is allowed to continue in an error state, and that can't be a good thing.
As Sid found out, the type mismatch is caused by a typo -- this shouldn't be allowed to happen: make sure every module you ever type any code in says Option Explicit at the top, and it'll never happen again... for your early-bound code (late-bound code is still vulnerable to typos, but that's another story for another time).
Lastly, note that several of the above mentioned issues would have been reported by Rubberduck's code inspections (disclaimer: I manage this open-source project) - including the typo, the implicit default member calls, and the absence of Option Explicit.

Can I dynamically count the number of times I reset an Excel Sheet?

Currently I have a reset button for my excel sheet which will clear the contents except the formulas I have. Is there a way to dynamically count how many times I "pressed" the reset button and clear contents?
This..
Public countR As Long
Sub Alternative1() 'This will return to 0 when you close the workbook
countR = countR + 1
MsgBox "The document has been cleared " & countR & " time(s)"
End Sub
or..
Sub Alternative2()
Dim rng As Range
Set rng = Range("A1") 'Change to some cell that isn't cleared by your code
rng.Value = rng.Value + 1
End Sub
and call them like..
Sub WhatYourCodeMaybeLooksLike()
Range("B1:C100").ClearContents
Alternative1
Alternative2
End Sub
The comment by reportgunner above is correct, but if you're asking for VBA options then look at module level variables.
Public x As Integer
Sub Button1_Click()
x = x + 1
MsgBox x
End Sub
x will begin as 0 when you open the workbook and will then be incremented each time Button1 is hit, in this case.
Slightly different are static variables which you can declare in the procedure with the code. Both will work fine in VBA.
The variable will often reset if your code hits errors during debugging. So the cell option might be preferable if you never want to lose track of the number.

Excel 2016 ComboBox Date Display versus Number

This seems to be a simplistic task to get the actual date to display in the combobox versus 43466 (a number). The code that everyone seems to be using is the following with
.Text:
Private Sub ComboBox20_Change()
ComboBox20.Text = format(ComboBox20.Text, "dd/mm/yyyy")
End Sub
OR . Value
Private Sub ComboBox20_Change()
ComboBox20.Value = format(ComboBox20.Value, "dd/mm/yyyy")
End Sub
I have even tried with .text and .value. Either one keeps giving me the following error:
Compile Error:
Wrong number of arguments or invalid property assignment
Any thoughts on what I must be missing, having a brain meltdown on the most mundane and seemingly easy task.
Problem approach
The problem seems to be when you are attempting to change the value in the combobox, is there a value to begin with? If it is empty, it is taking the default version of the date.
Solution approach
Try to set the value before it goes into the Change event.
Sample code and demonstration
Private Sub ComboBox1_Change()
ComboBox1.Value = Format(ComboBox1.Value, "dd/mm/yyyy")
End Sub
Private Sub UserForm_Activate()
Dim CounterDate As Long
Dim TxtDate As String
For CounterDate = 1 To 2
TxtDate = DateAdd("d", CounterDate, Now)
ComboBox1.AddItem (TxtDate)
ComboBox1.Value = TxtDate
Next CounterDate
End Sub
Further comments
As you may see as soon as you change it, it enters again the "Change" event, you may turn off the events as soon as you enter the cycle and then turn them on again if it is causing erratic behaviour on your pc -sometimes it does-.

Automatic reminder first working day of the month

I have an Excel tool that is used daily by a lot of people - each month they are expected to run a macro to report data to a central point.
Is there a way that I can call a macro such as this as the document is opened?
How would you go about doing this in the Workbook_Open event? Would you make it optional or give users no choice (i.e. auto submit on said day?)
This would potentially help me from chasing people up monthly
As a side note, if I gave users the 'option' - is there a less crude way of reminding them? For example if answer = vbNo Then range("A1") = "1" and then having an if statement within workbook open until they press yes which would set range ("A1") to 0 or similar?
Thanks
You are very much on the right track.
Make a reference worksheet in the workbook with the end-of-month dates listed in A1:A12, then place this code in the Workbook_Open event.
Private Sub Workbook_Open()
Dim dDate as Date
dDate = Application.WorksheetFunction.EoMonth(Date, 0)
With Worksheets("reference")
Dim rFound As Range
Set rFound = .Range("A1:A12").Find(dDate, lookat:=xlWhole, LookIn:=xlValues)
If Not rFound Is Nothing Then
If rFound.Offset(, 1) = 0 Then
Dim ret As Variant
ret = MsgBox("Would you like to submit data now?", vbYesNo)
If ret = vbYes Then
'run macro to submit data
rFound.Offset(, 1) = 1
'you may want to set this cell to 1 also if the user submits data manually so it knows for next time
Else
'set to zero to check for next time
rFound.Offset(, 1) = 0
End If
End If
End If
End With
End Sub
This is optional for the user, but will repeatedly ask them each time they open the book until they do submit for that month. Then it will wait until next month to ask again.
The problem with making it auto-submit on a given day is that what if the user never opens the workbook on said day?

Excel keeps running my macro

I have a workbook where several people will make an entry during the week.
Every entry is on its own row. Now i would like to have excel automatic insert the "Windows log-in name" of the user who made the entry, lets say on column K in that speciffic row.
I have found and tried to use the following script.
Function GetName(Optional NameType As String) As String
'Function purpose: To return the following names:
'Defaults to MS Office username if no parameter entered
'
'Formula should be entered as =GetName([param])
'
'For Name of Type Enter Text OR Enter #
'MS Office User Name "Office" 1 (or leave blank)
'Windows User Name "Windows" 2
'Computer Name "Computer" 3
'Force application to recalculate when necessary. If this
'function is only called from other VBA procedures, this
'section can be eliminated. (Req'd for cell use)
Application.Volatile
'Set value to Office if no parameter entered
If Len(NameType) = 0 Then NameType = "OFFICE"
'Identify parameter, assign result to GetName, and return
'error if invalid
Select Case UCase(NameType)
Case Is = "OFFICE", "1"
GetName = Application.UserName
Exit Function
Case Is = "WINDOWS", "2"
GetName = Environ("UserName")
Exit Function
Case Is = "COMPUTER", "3"
GetName = Environ("ComputerName")
Exit Function
Case Else
GetName = CVErr(xlErrValue)
End Select
End Function
I would then call GetName(2) from the relevant cell, but when a new user enter a new entry, all the previous user names are set to the new user.
Any help on this problem, are welcome
Thx
Taz
UPDATE:
Thx for the answers, they helped me get a bit further in solving my problem.
I have now come up with this code, but theres some strange things going on sometimes.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim User As String
User = Environ("UserName")
If Not Intersect(Target, Range("a7:a30")) Is Nothing Then
ActiveSheet.Unprotect
Application.EnableEvents = False
ActiveCell.Offset(0, 10).Value = User
Application.EnableEvents = True
ActiveSheet.Protect
End If
End Sub
This is pretty much working like it should, however it is possible to kinda fool the offset, so it will sometimes write the username only 9 offsets away.
Is it possible to change the code so i can write to a cell in a fixed column, on that row that is active ?
/Taz
With the help of this forum, i was able to make excel do what i wanted, i post the code here.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim row, col, user, ColCell As String
user = Environ("UserName")
col = "G" 'Set the Column ?
If Not Intersect(Target, Range("B7:B30")) Is Nothing Then
ActiveSheet.Unprotect
Application.EnableEvents = False
row = Split(Selection.Address, "$")(2) 'Get row number
ColCell = col & row
Range(ColCell).Value = user
'MsgBox "ColCell is : " & ColCell
Application.EnableEvents = True
ActiveSheet.Protect
End If
End Sub
But i have one question still, i have alot of sheets in my workbook, do i need to put this code in all the sheets, or is there a way that i can avoid this, and only have the code run from one place ?

Resources