Run Event Macro After Data Validation Selection - vba

I built up a data validation list on the sheet called report, I need to run a macro each time I select an item from the list. Now that I have this code below, but it doesn't work. It does run in VBA, but it will not run when I choose the Item in my worksheet, it seems like I didn't refer to the macros
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Address(True, True) = "$B$3" Then
Select Case Target
Case "ABCP"
Call Macro1
Case "Accounting Policy"
Call Macro2
Case Else
'Do Nothing
End Select
End If
End Sub

If you want to run the procedure when you have changed the value in B3 (picking from the data validation list, then you want a Worksheet_Change event macro, not a Worksheet_SelectionChange.
Additionally, if anything on the worksheet is going to change then you will want to disable events so the event macro does not attempt to run on top of itself.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$B$3" Then
On Error GoTo bm_Safe_Exit
Application.EnableEvents = False
Select Case Target.Value2
Case "ABCP"
Call Macro1
Case "Accounting Policy"
Call Macro2
Case Else
'Do Nothing
End Select
End If
bm_Safe_Exit:
Application.EnableEvents = True
End Sub
This should launch the correct sub procedure when B3 has a new value selected from the list. You would have to provide more details (and code) for m Macro1 and Macro2 if it continues to be problematic.

The above code appears to work fine for me.
Have you placed the code in the worksheet code? as opposed to a Module?

Related

How to Detect if a Cell is Changed by an "=IF()" Formula and not by a User

I read a lot of pages saying that, but none of them put the solution if the value change by an "if function" not by hand.
The code I get is that:
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Me.Range("A18:A30")) Is Nothing Then Exit Sub
Application.EnableEvents = False 'to prevent endless loop
On Error GoTo Finalize 'to re-enable the events
MsgBox "You changed THE CELL!"
Finalize:
Application.EnableEvents = True
End Sub
It only works if I change the value by hand.
Thank you in advance.
Another solution; instead of triggering your function every time when your worksheet recalculates, add a function in a module:
Function DetectChange() As Integer
MsgBox "You changed THE CELL!"
DetectChange = 0
End Function
Assuming the outcome of your formula is numeric:(otherwise outcome of function must be a empty string and the "+" must be "&")
Add to your IF-formula at the end ...+Detectchange()
Now there will be a msgbox only when your formula is recalculated
Edit by Darren Bartrup-Cook:
I found this code gave worked when the formula recalculated. It didn't fire if I changed a cell that doesn't affect the cell it's entered to and it didn't fire using Calculate Now or Calculate Sheet.
It did occasionally fire for all formula that I used the function in, but that seemed to be when I was debugging - maybe further investigation needed.
Public Function DetectChange()
MsgBox "You changed cell " & Application.Caller.Address
End Function
e.g.:
=IF(A1=1,A2,A3) & DetectChange() entered in cell A4 displays the message "You changed cell $A$4" if cells A1, A2 or A3 is changed.
Write this in Sheet1 and run the TestMe sub:
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Me.Range("A1:A30")) Is Nothing Then Exit Sub
Application.EnableEvents = False
On Error GoTo Finalize
MsgBox "You changed THE CELL!"
Finalize:
Application.EnableEvents = True
End Sub
Sub TestMe()
Range("A1") = 34
End Sub
It has worked quite ok on my PC.
If the cell is changed by a built-in Excel function, then the comment of #Vincent G states the correct answer:
Worksheet_Change event occurs when cells on the worksheet are changed by the user or by an external link. and This event does not occur when cells change during a recalculation. Use the Calculate event to trap a sheet recalculation.
If you want to track the calclulation event based on some changes at Range(A18:A30) this is a working solution:
Add a new Worksheet to your Workbook (Sheet2);
In the current Worksheet write the Calculate event:
Private Sub Worksheet_Calculate()
Dim cell As Range
For Each cell In Sheet2.Range("A18:A30")
If cell <> Sheet1.Range(cell.Address) Then
cell = Sheet1.Range(cell.Address)
End If
Next cell
End Sub
In the Sheet2 write an event, catching the changes.
As simple as #Vincent G says.
Private Sub Worksheet_Calculate()
Call YourFunction
End Sub

Passing Target to Sub in Excel VBA

In Excel 2010, I'm trying to pass 'Target' from a Worksheet_Change event to a subroutine. The sub checks if a change has occurred within a specific range and does certain things if it does. The problem I'm having is that target seems to behave differently in the sub that in the calling procedure. For instance, in the calling procedure I can use Target within an intersect, when I pass it to the sub and do the same thing I get a run time error (1004). My code is below, I'd be grateful if someone can inform me what I'm doing wrong.
'Code on sheet - this is on several sheets
Private Sub Worksheet_Change(ByVal Target As Range)
SubRout Target
End Sub
'Code in Module
Sub SubRout (ByVal Target As Range)
Dim ValidChange As Boolean
ValidChange = True
'Check if change on sheet was a change to cell in named range
If Intersect(Target, Names("WB4aWBSRange").RefersToRange) Is Nothing Then ValidChange = False
If ValidChange = True And Target.value <> "" Then
'Do stuff
End If
End Sub
The run time error occurs on the Intersect line, but if I move all the code up to the calling routine it works fine.
The error is not because of that. Error is because of Names("WB4aWBSRange").RefersToRange. You can't use it like that.
Use this
If Intersect(Target, Range("WB4aWBSRange")) Is Nothing Then ValidChange = False
Because is Nothing returns a Boolean value the first if statement isn't needed:
ValidChange = Not Intersect(Target, Range("WB4aWBSRange")) Is Nothing
I would rather not use the variable at all and do this instead:
If Not Intersect(Target, Range("WB4aWBSRange")) Is Nothing' then
If Target.value <> "" Then
'Do stuff
End If
End Sub

Run Macro Dropdown List Excel

I wrote this Macro out to copy and paste info from a previous sheet to the active sheet. I want to make this into a dropdown list but when using data validation, the macro doesn't run when it is picked. Attached is my code and I am wondering should I make a list box or should I stick with data validation? I know there's a way to make a macro run once clicked in a click box
Sub WorkDay1()
ActiveSheet.Range("A6:H44").Value = Worksheets("Route Sheet - Manhattan 1").Range("A6:H44").Value
End Sub
Sub WorkDay2()
ActiveSheet.Range("A6:H44").Value = Worksheets("2").Range("A6:H44").Value
End Sub
Sub WorkDay3()
ActiveSheet.Range("A6:H44").Value = Worksheets("3").Range("A6:H44").Value
End Sub
Sub WorkDay4()
ActiveSheet.Range("A6:H44").Value = Worksheets("4").Range("A6:H44").Value
End Sub
Assuming your dropdown list is in cell A1.
Paste this code into the worksheets code module.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Application.EnableEvents = False
If Not Intersect(Target, Range("A1")) Is Nothing Then
Select Case Target.Value
Case "WorkDay1"
WorkDay1
Case "WorkDay2"
WorkDay2
Case "WorkDay3"
WorkDay3
Case "WorkDay4"
WorkDay4
End Select
End If
Application.EnableEvents = True
End Sub
In the VBA Project explore double click the Sheet that you wish to run the macro on. This will open up the code module for that sheet. Then paste the code into that module.
Adding this colud will update the values when you select the worksheet.
Private Sub Worksheet_Activate()
Select Case Range("A1")
Case "WorkDay1"
WorkDay1
Case "WorkDay2"
WorkDay2
Case "WorkDay3"
WorkDay3
Case "WorkDay4"
WorkDay4
End Select
End Sub

VBA Excel: General change detection

Is there an object and/or function that can detect or represent a general change on a worksheet? Something similar to (for example) ComboBox1_Change() but could be applied to a whole worksheet. Almost something like Worksheet1_Change(). Any suggestions are welcome. Thanks.
The simplest would be to use the worksheet change event:
Private Sub Worksheet_Change(ByVal Target As Range)
MsgBox "Change Detected!"
End Sub
There are instances will this will throw you in to an infinite loop. Consider this code:
Private Sub Worksheet_Change(ByVal Target As Range)
Range("A1").Value = "Change"
End Sub
Set a breakpoint on the Range("A1") code and make a change somewhere else on the sheet and count how many time that breakpoint gets hit. When you get tired of hitting F5, stop the code and try this:
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Range("A1").Value = "Change"
Application.EnableEvents = True
End Sub
You'll see that the code only fires once. Which is probably what you're after.
It's very important that you have the Application.EnableEvents = True line in there, or else you'll get the appearance that your code isn't working (by default EnableEvents does not revert back to True at the end of the code).

How to call a Macro when a named range (cell) is changed

I am trying to call a macro named "RE_environmental" when the cell named "RE_1" is changed (i.e. they mark a X in the cell). I've tried several different variations of codes including these two and nothing is happening:
[The first code does work if I use the exact cell location and not the named cell. --> $E$62]
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "RE_1" Then
Call RE_environmental
End If
End Sub
AND
Private Sub Worksheet_Change(ByVal Target As Range)
If Range("Name").Select = "RE_1" Then
Call RE_environmental
End If
End Sub
--Thanks in Advanced and please let me know if you need more information.
Use your first answer but make this small change:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = Range("RE_1").Address Then
Call RE_environmental
End If
End Sub
Simple syntax mistake!
Edit: To stop RE_environmental from running once the cell is empty, put the code from RE_environmental inside a do-while (not isempty(Range("RE_1"))) as long as RE_environmental is emptying "RE_1". The user won't be able to edit cells while RE_environmental is running.
If Target is always single-cell range, you can use this one:
If Target.Address = Range("RE_1").Address Then
Call RE_environmental
End If
If Target can be multicell range use this one:
If Not Intersect(Target, Range("RE_1")) Is Nothing Then
Call RE_environmental
End If