VBA - Exiting out of MsgBox() [duplicate] - excel

This question already has answers here:
Why MS Excel crashes and closes during Worksheet_Change Sub procedure?
(3 answers)
Closed 1 year ago.
I haven't worked with VBA for a while, so my skills are a bit rusty. I've managed to put together a small script that will update the Date Contacted and Date Modified column I have in my excel sheet If I were to change the respective cell in column A. For all cells in column A, I set up a List by using the Data Validation tool. List = A, B, C, D.
The script should input the current date in Date Contacted (column H) when one of the list items is selected. If the cell is changed to a new item a message box will ask if the user wants to commit the changes. If yes, the Date Modified (column I) will be updated. If no, Column A should revert back to it's original self and neither one of the Date columns should be updated.
There are no bugs in the code, but when prompted to answer yes or no, clicking "no" continues to loop back to the message box. I am stuck in the loop and unsure how to escape.
Private Sub Worksheet_Change(ByVal Target As Range)
' Auto Date
Dim Cell As Range
Dim Answer As Integer
For Each Cell In Target
If Cell.Column = Range("A:A").Column Then
If Cells(Cell.Row, "H").Value <> "" And Cell.Value <> "" Then
Answer = MsgBox("Are you sure you want to make these changes?", vbYesNo)
If Answer = vbYes Then
Cells(Cell.Row, "I").Value = Int(Now)
Else
Application.Undo
End If
Else
Cells(Cell.Row, "H").Value = Int(Now)
End If
End If
Next Cell
End Sub

You need to turn off events before making any changes to the worksheet via the macro. Changes trigger the event and when your event makes changes, it re-triggers the event resulting in a loop, or in your case, a conditional loop.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
'Any code that makes changes to worksheet nested inside
Application.EnableEvents = True
End Sub

Related

Trigger Macro only when Cell Value is Increased

its me....again. I am currently trying to have a Macro trigger whenever a specific cell increases on a specific sheet.
After many attempts I have been able to get the Macro to trigger when the cell is changed (increasing or decreasing) but I cannot figure out a way to have this Macro trigger only when the specified cell increases in value.
I have tried to use simple Worksheet_Change with an If Then statement that calls the Macro when the cell value is changed. Again I can't get this to trigger only when the cell increases. Not sure it is possible or if I am even thinking about this is in the right way.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address "Range" Then
Call MyMacro
End If
End Sub
Thank you for any help in advance. This would be really neat and save alot of manual clicking around.
Here is the functioning Macro that I want to trigger when certain text is entered into a range.
Sub Auto_Print_Yellow_Caution()
Application.ScreenUpdating = False
Sheets("Saver").Shapes("Group 6").Copy
Sheets("Main").Select
ActiveCell.Offset(-1, 0).Select
ActiveSheet.Paste
ActiveCell.Select
Application.ScreenUpdating = True
End Sub
I already have my Workbook set up to track these words/phrases and return either a TRUE or FALSE value. If TRUE the associated Order Number is Printed into a Cell and a COUNTIFS formula is used to keep track of how many orders meet the TRUE condition. That number is then used to keep track of how many total of those orders there are. That works using the following
=IF(ISNUMBER(SEARCH("Completed",Main!G7)),TRUE)
-looks for specific word and returns TRUE
=IF(T3=TRUE,Main!A7,"")
-Returns order number
=IF(COUNTIF($U3:$U$200,"?*")<ROW(U3)-2,"",INDEX(U:U,SMALL(IF(U$2:U$200<>"",ROW(U$2:U$200)),ROWS(U$2:U3))))
-Sorts order numbers into list
=COUNTIF(T2:T135,TRUE)
-Counts number of orders
Hopefully this adds context to what I am trying to accomplish.
This will hopefully get you on the right track. As per your question it assumes this is required for a single cell only (and in this example code, that cell is B2). The trick is to store the new value, 'undo' the change, grab the old value, reverse the 'undo' by replacing the new value. Then you can test if the values are numbers and, if so, test if the new number is greater than the old number.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim newValue As Variant, oldValue As Variant
If Target Is Nothing Then Exit Sub
If Target.Cells.Count <> 1 Then Exit Sub
If Target.Column <> 2 Or Target.Row <> 2 Then Exit Sub ' example is using cell B2
Application.EnableEvents = False
newValue = Target.Value2
Application.Undo
oldValue = Target.Value2
Target.Value2 = newValue
Application.EnableEvents = True
If IsNumeric(oldValue) And IsNumeric(newValue) Then
If CDbl(newValue) > CDbl(oldValue) Then
Call MyMacro
End If
End If
End Sub
Here is some logic I can think of, you need to have a helper cell to store previous data and compare if it increased. In this sample my helper cell is B1 and the cell I want to track is A1
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KCells As Range
Set KCells = Sheet10.Range("A1")' The variable KeyCells contains the cells that will
If Not Application.Intersect(KCells, Range(Target.Address)) Is Nothing Then 'cause an alert when they are changed.
If Sheet10.Range("B1").Value < Sheet10.Range("A1").Value Then
MsgBox "Replace this to call macro"
Sheet10.Range("B1").Value = Sheet10.Range("A1").Value 'this is to save the current data incase you change it later.
End If
End If
End Sub

Convert IF/AND to VBA and extend to sheet

I have a spread sheet which is used for basic scheduling of tasks.
Dates for the calendar run along Row 1 from O-NO and everything below is job related including due dates.
I am trying to automatically add a note to the calendar section of the sheet when a date is added to column E. The word “Due Date” is update to the corresponding text row/date column.
Colum E = due dates, Columns O to NO (rows are infinite) are days Jan – Dec. I have created the cell formula =IF((AND($E452=$1:$1)),"Due Date","") which is cell specific.
I need to keep the cells clear of formulas because they are used for adding other details so a Macro is the way to go.
I thought I could convert the formula to a macro and then manipulate the code to do what I need across all of the calendar cells. Below is the result.
Sub DueDate()
'
' DueDate Macro
'
'
Range("IM451").Select
ActiveCell.FormulaR1C1 = "=IF((AND(RC5=R1)),""Due Date"","""")"
Range("IM452").Select
End Sub
Firstly I tried a number of ways just to get this macro to run automatically without having to manually run it. For some reason I couldn’t get it to work.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$A$1" Then
MACRO CODE HERE
End If
End Sub
Plus a couple of other versions
Second step was to get it to work across all of the calender cells, another fail.
Would really appreciate some assistance on this.
Thank you
CRB
If I understand what you're trying to do correctly, then try this:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim c As Range
Application.EnableEvents = False
If Target.Cells.Count = 1 And Target.Column = 5 Then
Set c = Range(Cells(Target.Row, "N"), Cells(Target.Row, "NO")).Find("Due Date")
If Not c Is Nothing Then c.ClearContents
Set c = Nothing
If IsDate(Target.Value) Then
Set c = Range("N1:NO1").Find(Target.Value)
If Not c Is Nothing Then Cells(Target.Row, c.Column).Value = "Due Date"
End If
End If
Application.EnableEvents = True
End Sub
When a date is entered in column E, this will look for that date in range N1:NO1, and if the date is found, will insert "Due Date" in the matching column of the target row.

Automatically Fetch Current Time in Excel

I am trying to build out a task tracker for my job that aggregates the amount of time I spend on various assignments.
Example rows of task tracker
Currently I am entering the start and finish times for each task manually with Ctrl + ;, Space, Ctrl + Shift +;. What I would like to do, if possible, is to have the start time column populate with the current time at whatever moment I set the drop down option to "Work in Progress," and then the end time column to do the same for whatever moment I change it to "Closed."
Drop Down Menu
Any ideas?
If the Drop Down is a Form Control (as opposed to an ActiveX control) then you could right-click it and choose Assign Macro.
It should default to something like DropDown1_Change, and you can click New.
Then paste in code "something like" this:
Sub DropDown1_Change()
If Range("A4") = 1 Then Range("A1") = Now()
End Sub
The first & last lines should already be populated for you.
You'd need to adjust the code to your needs. In this example:
The Drop Down is named Drop Down 1.
Cell A4 is the Cell Link for my Drop Down.
Cell A1 is the cell I want the date in.
I want to run the code when item # 1 is selected from the Drop Down's Input Range.
If your control happens to be an ActiveX DropDown/ComboBox, the steps are similar:
Right click the control and choose View Code.
You'll be taken immediately to the VBA Editor.
Paste the code.
The only way to do this, is using macro's.
In VBA (Excel -> Alt+F11) you can handle create events to handle things like cell changes.
The double click on the sheet you're entering your task tracker data and add the following code:
Private Sub Worksheet_Change(ByVal Target As Range)
End Sub
Now you can use the Target parameter to detect the cell which has been changed and then modify some other cell based on the changes cell.
So let's assume you have the dropdown in colum '4' and the begin and end time in column '5' and '6'. Then using the code below will update the begin and endtime field based on what state the taks has:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 4 Then
If Target.Value = "Work in Progress" Then
Me.Cells(Target.Row, 5).Value = Time
ElseIf Target.Value = "Closed" Then
Me.Cells(Target.Row, 6).Value = Time
End If
End If
End Sub
NOTE
You need to create an Excel workbook with macro's which require you to enable them - by default Excel disables macro's - so take note on enabling them when asked.
Try this code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim FirstRow, StatusColumn, CurrentRow, CurrentColumn As Double
FirstRow = 5 'Define here the first row number of data
StatusColumn = 5 'Define here the column number of Status
CurrentRow = Target.Row
CurrentColumn = Target.Column
If CurrentColumn = StatusColumn And CurrentRow >= FirstRow Then
Select Case CStr(Target.Value)
Case "Work In Progress":
Cells(CurrentRow, CurrentColumn + 2) = Format(Now, "MM.dd.yy hh:mm")
Cells(CurrentRow, CurrentColumn + 3) = ""
Case "Closed":
Cells(CurrentRow, CurrentColumn + 3) = Format(Now, "MM.dd.yy hh:mm")
Case Else:
'Some code here...
End Select
End If
End Sub

Auto-fill the date in a cell, when change is made into an adjacent cell

I found code to work in Excel that almost does what I need.
My need is to have today's date added automatically in one column's cell when a change is made in another column's cell. So if I click in Column M Row 20's cell & change data or add data (in this case it is a Status column with a dropdown list) then in Column N Row 20's cell it will put today's date or replace old date with today's date. (Every time Status dropdown is changed.)
This code does that for 2 different columns because I altered it.
The Problems:
If I insert rows it will put today's date in the newly inserted
rows or if I delete rows, let's say 3 rows it will add the date or
overwrite the date in the 3 rows below the 3 just deleted. This is
not good. I only want a date added if I make a change in the cell
itself. Simply auto add date when we add or change the status (Data)
in the cell to the left of it.
Also I need the top 9 rows not to be affected by this auto date
add.
Lastly if I double click in Column M Row 20's cell but do not
enter any data then click out of the cell it will still add date to
Column N Row 20's cell.
I found the original code at:
Auto-fill the date in a cell, when the user enters information in an adjacent cell
My version of the code is:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim A As Range, M As Range, X As Range, Inte As Range, r As Range
Set A = Range("M:M,X:X")
Set Inte = Intersect(A, Target)
If Inte Is Nothing Then Exit Sub
Application.EnableEvents = False
For Each r In Inte
r.Offset(0, 1).Value = Date
Next r
Application.EnableEvents = True
End Sub
These modification take care of your first two specifications.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("M:M,X:X"), Range("10:" & Rows.Count)) Is Nothing Then
If Target.Count < Columns.Count Then
On Error GoTo bm_Safe_Exit
Application.EnableEvents = False
Dim r As Range
For Each r In Intersect(Target, Range("M:M,X:X"), Range("10:" & Rows.Count))
With r.Offset(0, 1)
.Value = Now 'use Now to retain the time as well as the date
.NumberFormat = "dd-mmm-yyyy hh:mm:ss" 'change to what you prefer
End With
Next r
End If
End If
bm_Safe_Exit:
Application.EnableEvents = True
End Sub
As far as the third, I would humbly suggest that you get used to using the preferred method of tapping Esc to abandon an 'in-cell' edit rather than Enter↵ or selecting another cell. Using Esc does not change the value in the cell and the Worksheet_Change event macro is not triggered. Using Enter or selecting another cell DOES change the value in the cell and coding against lackadaisical practises is simply not worth the overhead when proper keyboard practises could be applied.
Addendum:
If your hand is still on the mouse, you can also click the × in the formula bar to [Esc] an in-cell edit.
        

vba Change event when data validation selected

Hi I have a workbook that in Column C there is data validation drop down list. I'm tryinto code so that when a specific status is selected in the drown down (i.e. "Verification") Column I will automatically enter "Verification Unprocessed". Column I also has data validation and a drop down list. I've searched all over and can't seem to find a code that identifies a worksheet change event from a data validation drop down list. Thanks!
You fact that you have a drop-down list is not important. The Worksheet Change event will fire regardless of how the cell is changed. All you need to do is check if the Target variable in the event is in the right column, then do what you need to do. Sample code:
Private Sub Worksheet_Change(ByVal Target As Range)
With Target
If .Count = 1 Then
If .Row > 1 And .Column = 3 Then
If .Value = "specific status" Then
.Offset(0, 6).Value = "Verification Unprocessed"
Else
.Offset(0, 6).ClearContents
End If
ElseIf .Column = 5 Then
If .Value = Date Then
Call Lilly
End If
End If
End If
End With
End Sub
Let me know if you need further information.
EDIT: Incorperated your original code.

Resources