Merging multiple Worksheet_SelectionChange - excel

I have got no problem in running one Private Sub Worksheet_SelectionChange , but when i add multiple Worksheet_SelectionChange events it is not running. Later, i came to know that it is not possible running different worksheet selection change events in the same sheet.
I am having four different Private Sub Worksheet_SelectionChange events, trying to merge them with the help of various sites but none worked to me, as per my understanding.
Could i get some help,
1.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cells1 As Range
Set cells1 = ActiveSheet.Range("B1:B27")
If Not (Intersect(Target, cells1) Is Nothing) Then
ActiveSheet.Range("B30").Value = Target.Value
End If
End Sub
2.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cells2 As Range
Set cells2 = ActiveSheet.Range("C1:C27")
If Not (Intersect(Target, cells2) Is Nothing) Then
ActiveSheet.Range("C30").Value = Target.Value
End If
End Sub
3.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cells3 As Range
Set cells3 = ActiveSheet.Range("S1:S27")
If Not (Intersect(Target, cells3) Is Nothing) Then
ActiveSheet.Range("S30").Value = Target.Value
End If
End Sub
4.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cells4 As Range
Set cells4 = ActiveSheet.Range("T1:T27")
If Not (Intersect(Target, cells4) Is Nothing) Then
ActiveSheet.Range("T30").Value = Target.Value
End If
End Sub
I appreciate your help.
Thank you.

You can use a switch (select case) within your change event to allow options for which will occur.
Mock-up:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Row > 27 then Exit Sub
Select Case Target.Column
Case 2, 3, 19, 20
Cells(30,Target.Column).Value = Target.Value
End Select
End Sub
I have added the Exit Sub check for if the row > 27, as your ranges are 1:27, for each of the Columns. This replaces the Intersect() check.
You perform the same action based on the Target.Column, so that is the only other parameter to verify and utilize.

Related

Hide Rows in Excel based on cell value

I have a multiple selection, Option buttons, that change the value of cell D7 from 1 to 5, depending on choice. I want to unhide rows 16 to 26 if value is 1 and hide them if it's different, and so on for every other value.
But I can't even get this to work at all, and I'm not sure what I'm doing wrong.
Update: If I change the cell value, nothing happens, but if I delete all contents and add a value it gives: "Argument not optional", and it highlights this part of the code for me:
Private Sub Worksheet_Change(ByVal Target as Excel.Range)
Thank you
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If IsNumeric(Target) And Target.Address = "$D$7" Then
Select Case Target.Value
Case 0 To 90: Cell_Hider
End Select
End If
End Sub
Sub Cell_Hider(ByVal Target As Range)
If Range("$D$7").Value = "1" Then
Rows("16:26").EntireRow.Hidden = False
Else
Rows("16:26").EntireRow.Hidden = True
End If
End Sub
Your procedure Cell_Hider needs an argument but your code calls it without argument Case 0 To 90: Cell_Hider
You call Cell_Hider if the value is between 0 and 90 then that procedure needs the value to be 1 to show the rows and 0 or 2 to 90 will hide them. If you put 100 in that cell nothing happens at all. Sounds not like what you expect to me.
"1" is text not a number!
Something like the following would work:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
If IsNumeric(Target) And Target.Address = "$D$7" Then
Select Case Target.Value
Case 0 To 90: Cell_Hider Target
End Select
End If
End Sub
Sub Cell_Hider(ByVal Target As Range)
If Target.Value = 1 Then
Target.Parent.Rows("16:26").EntireRow.Hidden = False
Else
Target.Parent.Rows("16:26").EntireRow.Hidden = True
End If
End Sub
Even though it doesn't look logic to me and I'm not sure what you are exactly trying to achieve.
Note that you can shorten it to
Sub Cell_Hider(ByVal Target As Range)
Target.Parent.Rows("16:26").EntireRow.Hidden = Not Target.Value = 1
End Sub
Hide/Unhide Rows on Cell Change
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim sCell As Range: Set sCell = Me.Range("D7")
If Intersect(sCell, Target) Is Nothing Then Exit Sub
If IsNumeric(sCell.Value) Then
HideRows sCell
End If
End Sub
Sub HideRows(ByVal SourceCell As Range)
If SourceCell.Value = 1 Then
SourceCell.Worksheet.Rows("16:26").Hidden = False
Else
SourceCell.Worksheet.Rows("16:26").Hidden = True
End If
End Sub

How to trigger macros when clicking on a specific cell

I want to trigger two independent macros each based on different cells. To be specific, I want to trigger the Orange macro when cell E8 is clicked. And the Factiva macro when cell E9 is clicked. This is the code I came up with so far,,,, but does not work... The two macros are related to showing a graph(normal bar graph) !
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Selection.Count = 1 Then
If Not Intersect(Target, Range("E9")) Is Nothing Then
Call Factiva
End If
End If
End Sub
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Selection.Count = 1 Then
If Not Intersect(Target, Range("E8")) Is Nothing Then
Call Orange
End If
End If
End Sub
Sub Factiva()
'
' Factiva Macro
'
'
ActiveSheet.Shapes.Range(Array("factiva")).Visible = msoFalse
ActiveSheet.Shapes.Range(Array("factiva")).Visible = msoTrue
Application.CommandBars("Selection").Visible = False
End Sub
Sub Orange()
'
' Orange Macro
'
'
ActiveSheet.Shapes.Range(Array("Orange Business")).Visible = msoFalse
ActiveSheet.Shapes.Range(Array("Orange Business")).Visible = msoTrue
Application.CommandBars("Selection").Visible = False
End Sub
You can't have two procedures with the same name in the same module, or two handlers for the same worksheet event in a Worksheet module. Option Explicit isn't valid anywhere else than in a module's declarations section, at the very top (you can't have it between procedures).
You need the SelectionChange handler to determine which cell is selected, and decide which macro it wants to invoke accordingly.
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Selection.Count <> 1 Then Exit Sub 'bail out immediately instead of nesting
Select Case True
Case Not Intersect(Target, Range("E9")) Is Nothing
Factiva 'note: Call keyword is redundant
Case Not Intersect(Target, Range("E8")) Is Nothing
Orange 'note: Call keyword is redundant
'Case ...
End Select
End Sub
Note that if that is the only code that needs to invoke the Factiva and Orange procedures, then they can both be made Private. Also, consider renaming your procedures using meaningful names that start with a verb, e.g. ShowFactivaShape, or ShowOrangeBusinessShape.
In fact, you could parameterize the code and remove one of the two:
Private Sub ShowShape(ByVal shapeName As String)
ActiveSheet.Shapes(shapeName).Visible = msoTrue
Application.CommandBars("Selection").Visible = False
End Sub
Note that there shouldn't be a need to set visibility to msoFalse before you set it to msoTrue, and the Shapes.Range(Array(...)) is superfluous, since you're only interested in a single named Shape.
The SelectionChange handler would then look like this:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Selection.Count <> 1 Then Exit Sub 'bail out immediately instead of nesting
Select Case True
Case Not Intersect(Target, Range("E9")) Is Nothing
ShowShape "Factiva"
Case Not Intersect(Target, Range("E8")) Is Nothing
ShowShape "Orange Business"
'Case ...
End Select
End Sub
Consider making a similar HideShape procedure if you need to hide "Orange Business" when "Factiva" is shown, and vice-versa - or better, consider adding a Optional ByVal isVisible As Boolean = True parameter to ShowShape, and then you can use the same procedure for both purposes:
Private Sub ShowShape(ByVal shapeName As String, Optional ByVal isVisible As Boolean = True)
ActiveSheet.Shapes(shapeName).Visible = IIf(isVisible, msoTrue, msoFalse)
Application.CommandBars("Selection").Visible = False
End Sub
That way you can easily show/hide shapes as needed:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Selection.Count <> 1 Then Exit Sub 'bail out immediately instead of nesting
Select Case True
Case Not Intersect(Target, Range("E9")) Is Nothing
ShowShape "Factiva"
ShowShape "Orange Business", isVisible:=False
Case Not Intersect(Target, Range("E8")) Is Nothing
ShowShape "Orange Business"
ShowShape "Factiva", isVisible:=False
'Case ...
End Select
End Sub

Show userform if A11:A29 or G8 is clicked

I used to have the following code that worked to bring up a user form (calendar)when A11:A29 or G8 was clicked:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Application.Intersect(Target, Range("A11:A29")) Is Nothing Then DatePickerForm.Show
If Not Application.Intersect(Target, Range("G8")) Is Nothing Then DatePickerForm.Show
End Sub
I wound up having to scrap that user form due to issues with MS MonthView Control 6.0. I moved to a different calendar found here. The site suggests using double click anywhere on the sheet to show the userform. This works as designed but does so for any cell whereas I would like to limit it to only cells A11:A29 and G8, either by double clicking or clicking once. I tried modifying the code on the page to:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim ARange As Range
Dim GRange As Range
Set ARange = Range("A11:A29")
Set GRange = Range("G8")
If Not Application.Intersect(Target, ARange) Is Nothing Then DatePickerForm.Show
If Not Application.Intersect(Target, GRange) Is Nothing Then DatePickerForm.Show
End Sub
I get run-time error 91, object variable or with block not set. Debugging highlights the "If isdate" line below:
Private Sub UserForm_Activate()
If IsDate(Target.Value) Then
Calendar1.Value = Target.Value
End If
Call MoveToTarget
End Sub
It is because Target is Range object familiar only inside the specific Worksheet code module it is placed (like a local variable) , oo it's not recognized inside the DatePickerForm form module.
Use:
Private Sub UserForm_Activate()
If IsDate(ActiveCell.Value) Then Calendar1.Value = ActiveCell.Value
End If
Also, there is a more efficient way to see if Target falls inside multiple Range, use Union to merge multiple Ranges into one Range, see code below:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim UnionRange As Range
Set UnionRange = Application.Union(Range("A11:A29"), Range("G8"))
If Not Application.Intersect(Target, UnionRange) Is Nothing Then DatePickerForm.Show
End Sub

Hide commandbutton based on cell value excel vba

I am trying to hide a commandbutton based on a specific cell value. I have looked up several codes and pasted them in excel (in the vba form when right clicking the sheet and selecting "view code").
What am I doing wrong?
Here's one of the codes I've tried:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Range("A1") = 0 Then ActiveSheet.CommandButton1.Visible = False
If Range("A1") = 1 Then ActiveSheet.CommandButton1.Visible = True
End Sub
Make sure you enable events before using your code. Also, you must place your code in Worksheet module, not in regular module. To enable events, use this simple sub.
Sub Enable_events()
Application.EnableEvents = True
End Sub
please run this first:
Sub enable_()
Application.EnableEvents = True
End Sub
and then your Code will run perfectly:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Range("A1") = 0 Then ActiveSheet.CommandButton1.Visible = False
If Range("A1") = 1 Then ActiveSheet.CommandButton1.Visible = True
End Sub
Your code is confusing, for a number of reasons.
Range, when it's not qualified with a Worksheet object, implicitly refers to the ActiveSheet, i.e. ActiveSheet.Range... but when it's in a worksheet's code-behind, it implicitly refers to that worksheet's Range property, i.e. Me.Range. Because the meaning of an unqualified Range call depends on context, it's best to always qualify it with an explicit Worksheet object.
So if you're in the code-behind module for Sheet1, then Range("A1") is equivalent to Sheet1.Range("A1"), or even better, Me.Range("A1").
The two conditions will be evaluated every time, but only one of them needs to be: it's inefficient.
Truth is, you don't need to assign a Boolean literal - a Boolean expression is much cleaner.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Me.CommandButton1.Visible = (Me.Range("A1") = 1)
End Sub
Now, assuming Application.EnableEvents returns True, that code will run every time the selection changes, which is rather overkill.
Handle the Worksheet.Change event instead, and only act when the modified cell is A1:
Private Sub Worksheet_Change(ByVal Target As Range)
If Application.Intersect(Target, Me.Range("A1")) Is Nothing And Target.Count <> 1 Then
' we don't care about that cell: bail out
Exit Sub
End If
Me.CommandButton1.Visible = (Me.Range("A1") = 1)
End Sub
Please try this code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A1")) Is Nothing Then
If Selection.Cells.Count = 1 Then
If Range("A1") = 0 Then ActiveSheet.CommandButton1.Visible = False
If Range("A1") = 1 Then ActiveSheet.CommandButton1.Visible = True
End If
End If
End Sub
Hope this help.

Open UserForm upon selecting any cell in a table

I am using the following code to open a userform upon cell selection in a table by user, where each table has 30 rows with multiple tables in one sheet. I will have to write 100s of lines again and again.
I know this is not an efficient way to do so. How do I make this code simpler and shorter without affecting functionality?
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Address = "$D$31:$E$31" Then
Open_Text_Form
End If
If Target.Address = "$D$32:$E$32" Then
Open_Text_Form
End If
If Target.Address = "$D$33:$E$33" Then
Open_Text_Form
End If
If Target.Address = "$D$34:$E$34" Then
Open_Text_Form
End If
If Target.Address = "$D$35:$E$35" Then
Open_Text_Form
End If
If Target.Address = "$D$36:$E$36" Then
Open_Text_Form
End If
If Target.Address = "$D$37:$E$37" Then
Open_Text_Form
End If
End Sub
You can use the Intersect function to find if a range (cell) is inside of a given range. Without knowing how the data is setup in the sheet, I can't say what the best way to check is. If the multiple "tables" on your sheet are actually Excel tables, you can do something like this to have it check if you have clicked inside of one of them.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim tableRange As Range
For i = 1 To ListObjects.Count
If i = 1 Then
Set tableRange = ListObjects(i).DataBodyRange
Else
Set tableRange = Application.Union(tableRange, ListObjects(i).DataBodyRange)
End If
Next
If tableRange Is Nothing Then Exit Sub
If Not Application.Intersect(Target, tableRange) Is Nothing Then
Open_Text_Form
End If
End Sub
However if the "tables" in your sheet are just normal data ranges you could define them in a named range and all you would need to do is
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Application.Intersect(Target, Range("MyNamedRange")) Is Nothing Then
Open_Text_Form
End If
End Sub

Resources