I am trying to create a drop down list that will run a macro with each option selection. The drop down list will contain "Google" and New Businesses". When Google is selected, I need a certain macro to run. I have the macros codes ready to go, just wondering if this is even possible since I am working on a Macbook.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("F4")) Is Nothing Then
Select Case Range("F4")
Case "Google": Google
Case "New Businesses": New_Businesses
End Select
End If
End Sub
The code above is located in the first sheet with Worksheet and Change as the drop down options. The following codes are located in Module1:
Sub Google()
'First Macro
Call GoogleManagementFee
'Second Macro
Call HideTermsAndConditions
End Sub
Sub GoogleManagementFee()
Sheets("THIRD-PARTY").Range("C26").Value = 0
End Sub
Sub HideTermsAndConditions()
Worksheet("SOW").Range("54:110").Rows.Hidden = True
End Sub
Sub New_Businesses()
Call UnhideTermsAndConditions
Call ManagementFee10
End Sub
Sub UnhideTermsAndConditions()
Range("54:110").Rows.Hidden = False
End Sub
Sub ManagementFee10()
Sheets("THIRD-PARTY").Range("C26").Value = 0.10
End Sub
I believe these codes should enable macros to run when I select either Google or New Businesses from the drop down menu I created. I'm wondering if I need to download ActiveX or if I simply did something wrong with the codes.
Related
I've created a drop down menu through data validation for workbook navigation. The following is a snippet of code I have for the drop down box to change worksheets in the workbook:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Not (Application.Intersect(Range("J4"), Target) Is Nothing) Then _
ThisWorkbook.Sheets("Home").Visible = False
ThisWorkbook.Sheets(Target.Value).Activate
ThisWorkbook.Sheets(Target.Value).Visible = True
ThisWorkbook.Sheets("Imported Data").Visible = False
End Sub
The code is meant to hide all other worksheets that are accessible by the drop down list besides the one selected. I have about 10 tabs and this code has worked perfectly to achieve the basic goal of navigation. However, some pages have formulas and when you update data in the cells meant for calculations the workbook jumps to a random worksheet in the workbook that is not at all referenced in this sub.
Is there some way to have my worksheets not try to do anything with this sub unless the dropdown menu itself is changed?
Bonus (less important) Question: is there a way to make the drop box default to (blank) unless the menu itself is accessed?
Then _
The space followed by an underscore _ means that the current statement isn't finished yet but continues on the next line. Right now the last 3 lines will run whenever there is a change in the worksheet. Put the entire code in If-Endif.
Also avoid unnecessary use of On Error Resume Next. Use proper error handling.
You need to make the sheet visible before you activate it and not vice versa.
Try this
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Whoa
If Not (Application.Intersect(Range("J4"), Target) Is Nothing) Then
ThisWorkbook.Sheets("Home").Visible = False
ThisWorkbook.Sheets(Target.Value).Visible = True
ThisWorkbook.Sheets(Target.Value).Activate
ThisWorkbook.Sheets("Imported Data").Visible = False
End If
Letscontinue:
Exit Sub
Whoa:
MsgBox Err.Description
Resume Letscontinue
End Sub
is there a way to make the drop box default to (blank) unless the menu itself is accessed?
If you have created it with Data Valdation then insert a blank value in the list.
I have created a macro that allows a user to select an option from a dropdown list which unhides selected rows that corresponds with their selection. The problem is when I protect the sheet I get the following error "Run-time error '1004'" when I select an option for the drop down list. I need this sheet to be protected so the user cannot touch the data sets shown. Here is a sample code (original version is very long):
Private Sub Worksheet_Change(ByVal Target As Range)
ActiveSheet.Activate
If Not Application.Intersect(Range("C15"), Range(Target.Address)) Is Nothing Then
Select Case Target.Value
Case Is ="Option 1"
Rows("17:75").EntireRow.Hidden = True
Case Is ="Option 2"
Rows("17:28").EntireRow.Hidden = False
End Select
End If
End Sub
I've been reading other threads and I've come across a few options that said I need to Unprotect and Protect my sheet but I'm not to sure how to add this to the code above. And if this is the best option for what I am trying to accomplish
Option 1
Sub UnprotectAll()
Dim sh As Worksheet
For Each sh In ActiveWorkbook.Worksheets
sh.Unprotect Password:=yourPassword
Next sh
End Sub
Sub ProtectAll()
Dim sh As Worksheet
For Each sh In ActiveWorkbook.Worksheets
sh.Protect Password:=yourPassword
Next sh
End Sub
Option 2 - Adding this code somewhere below
UserInterFaceOnly:=True
Any suggestions in how I can accomplish this? And what the full code would look like?
Thanks so much!
#ExcelNoob I’ve made the following assumptions based on your question:
Only the active sheet is relevant
You formatted cell C15 as not Locked (when the sheet is unprotected, right click C15 /format/protection and uncheck ‘locked’ & ‘hidden’
You have indicated the correct rows you want hidden or not (seem a bit odd?)
There are only 2 options
That being the case, the minimum code below will do what you ask. If you want to use a specific password, just put it between the double quotation marks.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Range("C15"), Target) Is Nothing Then
ActiveSheet.Unprotect Password:=""
If Range("C15").Value = "Option 1" Then
Rows("17:75").Hidden = True
ElseIf Range("C15").Value = "Option 2" Then
Rows("17:28").Hidden = False
End If
ActiveSheet.Protect Password:=""
End If
End Sub
As per above, but if you don't want to protect/unprotect, put your drop down in a form and use :
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Sheet1.Protect "Password", UserInterfaceOnly:=True
End Sub
Where "password" is changed to whatever password you want.
This is just an example of what I want to do. I have an elaborate macro that I want to do different things depending on whether it was called by another macro or not.
sub Example()
Call MyCode
end sub
sub MyCode()
If Called by Example GoTo SkipNextLine
Do these things
exit sub
SkipNextLine:
Do other things
end sub
You can create hidden name (which, actually, isn't tied to range). Think of it as global variable. The difference between global variable and this name is that name is persisted in workbook when you close it. When you open workbook again - you can start using it without any initialization. As a bonus, this name won't be displayed in Name Manager. The defining of name is required only once.
Sub SetHiddenName()
Names.Add Name:="Caller", RefersTo:="StartValue", Visible:=False
End Sub
Sub FF()
Names("Caller").Value = "FF"
Call SS
End Sub
Sub SS()
Select Case [Caller]
Case "FF": MsgBox "Called by FF" '...
Case "ZZ": MsgBox "Called by ZZ"
End Select
End Sub
A simple approach would be to use arguments and parameters.
Sub Example()
Call MyCode("Example")
End Sub
Sub Example2()
Call MyCode("Example2")
End Sub
Sub MyCode(Origin as String)
Select Case Origin
Case "Example"
'Do stuff here
Case "Example2"
'Do other stuff here
End Select
End Sub
I made my way to this post wanting a macro that changed things on the sheet, but not wanting to kick off event driven macros. In case it's also useful for someone else, it's possible to turn these off in excel using Application.EnableEvents in the parent macro using:
Sub parentMacro()
Application.EnableEvents = False
'Do stuf here
Application.EnableEvents = True
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
'this now only is called on worksheet changes outside of parent macro,
'as it's disabled while parent runs
'Note: This disables all event macros running, so might not be perfect for all cases
End Sub
I don't know where i have gone wrong. The Script works but it doesn't automatically run unless i go into the VBA application and click the play button for the script to run. Can someone help?
Private Sub HideChart1()
If ActiveWorkbook.Sheets("User Interface").Range("F8") = "Yes" Then
ActiveWorkbook.Sheets("Sheet1").ChartObjects("Chart 6").Visible = True
Else
ActiveWorkbook.Sheets("Sheet1").ChartObjects("Chart 6").Visible = False
End If
End Sub
Handle SheetChange, and call your procedure in there.
Private Sub Worksheet_Change(ByVal Target As Range)
HideChart1
End Sub
Done. Don't implement logic in event handlers, it's the first Gate of Hell and spaghettification. Having a separate, dedicated procedure for it is perfect - all you need is something that calls it automatically.
If HideChart1 is implemented in its own standard module, you'll need to make it Public to be able to call it from a worksheet's code-behind; add Option Private Module at the top of that module to avoid exposing members as macros and/or worksheet functions.
You want to use a Worksheet Change event.
Untested, but should work. Put this in your "User Interface" worksheet module.:
Private Sub Worksheet_Change(ByVal target As Range)
If target = Range("F8") And target.Value = "Yes" Then
ActiveWorkbook.Sheets("Sheet1").ChartObjects("Chart 6").Visible = True
Else
ActiveWorkbook.Sheets("Sheet1").ChartObjects("Chart 6").Visible = False
End If
End Sub
With Worksheet Change, I don't think (keyword "think") you need to specify the worksheet the Range("F8") is expected to be on, since it's by definition, the activesheet. If you want though, add the sheet name before that to be sure.
If my comment is correct, then you'll need something like this:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("F8")) Is Nothing Then
If Target.Worksheet.Range("F8").Value = "Yes" Then
ActiveWorkbook.Sheets("Sheet1").ChartObjects("Chart 6").Visible = True
Else
ActiveWorkbook.Sheets("Sheet1").ChartObjects("Chart 6").Visible = False
End If
End If
End Sub
You can find more information about the worksheet change event here
automatically execute an Excel macro on a cell change
The key takeaway from that question, is to put the code in the worksheet module, not a regular module, or the workbook module.
I am having a problem with Excel crashing, when I run VBA code on an excel sheet.
I'm trying to add the following formula on worksheet change:
Private Sub Worksheet_Change(ByVal Target As Range)
Worksheets("testpage").Range("A1:A8").Formula = "=B1+C1"
End Sub
When this code is run i get a message saying "excel has encountered a problem and needs to close" and excel closes.
If I run the code in the Worksheet_Activate() procedure, it works fine and doesn't crash
Private Sub Worksheet_Activate()
Worksheets("testpage").Range("A1:A8").Formula = "=B1+C1"
End Sub
But I really need it to work in the Worksheet_Change() procedure.
Has anyone experienced similar crashes when using the Worksheet_Change() event and can anyone point in the right direction to fix this issue ?
I recommend this when using Worksheet_Change
You do not need the sheet name. In a Sheet Code Module, an unqualified Range reference refers to that sheet. That said, it is clearer to use the Me qualifier. If you are trying to use another sheet, then qualify the range reference with that sheet.
Whenever you are working with Worksheet_Change event, always switch Off events if you are writing data to any cell. This is required so that the code doesn't retrigger the Change event, and go into a possible endless loop
Whenever you are switching off events, use error handling to turn it back on, else if you get an error, the code will not run the next time.
Try this
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Whoa
Application.EnableEvents = False
Me.Range("A1:A8").Formula = "=B1+C1"
Letscontinue:
Application.EnableEvents = True
Exit Sub
Whoa:
MsgBox Err.Description
Resume Letscontinue
End Sub
Few other things that you may want to know when working with this event.
If you want to ensure that the code doesn't run when more than one cell is changed then add a small check
Private Sub Worksheet_Change(ByVal Target As Range)
'~~> For Excel 2003
If Target.Cells.Count > 1 Then Exit Sub
'
'~~> Rest of code
'
End Sub
The CountLarge was introduced in Excel 2007 onward because Target.Cells.Count returns an Long value which can error out in Excel 2007 becuase of increased total cells count.
Private Sub Worksheet_Change(ByVal Target As Range)
'~~> For Excel 2007
If Target.Cells.CountLarge > 1 Then Exit Sub
'
'~~> Rest of code
'
End Sub
To work with all the cells that were changed use this code
Private Sub Worksheet_Change(ByVal Target As Range)
Dim aCell As Range
For Each aCell In Target.Cells
With aCell
'~~> Do Something
End With
Next
End Sub
To detect change in a particular cell, use Intersect. For example, if a change happens in Cell A1, then the below code will fire
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("A1")) Is Nothing Then
MsgBox "Cell A1 was changed"
'~~> Your code here
End If
End Sub
To detect change in a particular set of range, use Intersect again. For example, if a change happens in range A1:A10, then the below code will fire
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("A1:A10")) Is Nothing Then
MsgBox "one or more Cells in A1:A10 range was changed"
'~~> Your code here
End If
End Sub
Note: If you were getting an error earlier and you made the above changes and If your code is still not working then it is possible that the events have not been reset. In the Immediate Window, type Application.EnableEvents = True and press the ENTER key. This will reset it to True. If you do not see the Immediate Window, the press the shortcut key Ctl+G to launch the Immediate Window.
Excel was crashing, not the VBA function.
The events were not disabled and the call stack was filled by an infinite loop of OnChange events.
A little advice that helps finding this type of errors: set a breakpoint on the first line of the event, then execute it step by step pressing F8.
Also this solution is good:
Option Explicit
Private Busy As Boolean
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Busy Then
Busy = True
Range("A1:A8").Formula = "=B1+C1"
Busy = False
End If
End Sub