How to send variables between a sheet and book? - excel

Ultimately, I'm trying to highlight cells when focus moves away from a workbook.
Here's my code (In ThisWorkbook):
Public s As Range
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
s = Selection
End Sub
Private Sub Workbook_Deactivate()
s.Interior.ColorIndex = xlColorIndexNone
s.Interior.Color = RGB(0, 0, 0)
End Sub
Private Sub Workbook_Activate()
s.Interior.ColorIndex = xlColorIndexNone
s.Interior.Color = RGB(100, 204, 204) ' Blue
End Sub
But I'm getting an error on the first s.Interior.ColorIndex encountered:
Object variable or With block variable not set
Here's some images of my env:
Sheet1
ThisWorkbook (Error highlighted):

There are a few issues:
1) In order to be visible throughout the project, Public variable declarations must be in a standard code module. Thus the line
Public s As Range
shouldn't be in ThisWorkbook but should be in a standard code module.
2) s = Selection should be changed to Set s = Selection
3) The sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Set s = Selection
End Sub
Should be in a sheet module (and repeated for every sheet that you want this for). It isn't a syntax error to have it in ThisWorkbook, but it won't work as intended.
4) It is dangerous to assume that s is defined whenever the activate or deactivate is triggered. You should guard against that. Something like:
Private Sub Workbook_Activate()
If s Is Nothing Then
Set s = Selection
Exit Sub
End If
s.Interior.ColorIndex = xlColorIndexNone
s.Interior.Color = RGB(100, 204, 204) ' Blue
End Sub
With something similar for Deactivate.

Related

Merging multiple Worksheet_SelectionChange

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.

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

One macro running , the other does not

I am importing currency data from a website on a click event.
The import works and its called by this code:
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Selection.Count = 1 Then
If Not Intersect(Target, Range("F13")) Is Nothing Then
Call GetCurrency
End If
End If
If Selection.Count = 1 Then
If Not Intersect(Target, Range("F14")) Is Nothing Then
Call UpdateCurrency
End If
End If
End Sub
If the cell F13 is clicked, the GetCurrency macro runs, imports the data, wonderful.
But clicking F14 causes nothing.
The update currency macro looks like this
Sub UpdateCurrency()
Range("N15").Value = Range("I19").Value
Range("N14").Value = Range("I26").Value
Range("N16").Value = Range("I22").Value
End Sub
This should just update some other cells in order to make another formula work properly. Question is, why does clicking the cell F14 not run the UpdateCurrency function?
It think you need to change the if statements a bit.
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Selection.Count = 1 Then
If Target = Range("F13") Then
If Not Intersect(Target, Range("F13")) Is Nothing Then
Call GetCurrency
End If
Else
If Not Intersect(Target, Range("F14")) Is Nothing Then
Call UpdateCurrency
End If
End If
End If
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.

Keep Listbox at top of Scrolling Worksheet [duplicate]

I have an excel workbook with two shapes on Sheet1 like below
My Requirement is when the user is navigating towards right side of sheet i.e. Towards headers24, header25 and so on ,I want the two shapes on the sheet to move towards the right side with the user.
Can someone Please suggests any ideas for this.
Thanks
Try this.. yep, its easy..
Place this code in the worksheet module where the shapes exist.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
With ActiveSheet.Shapes(1)
.Left = ActiveWindow.VisibleRange(2, 2).Left
.Top = ActiveWindow.VisibleRange(2, 2).Top
End With
End Sub
The coordinate (2, 2) is where you want the shape to be fixed at as you scroll along with the keyboard.
But, it would be annoying to work without the scroll bar on a huge worksheet. so alternatively I think you can use refresh ontime, place this code in a Module
Private eTime
Sub ScreenRefresh()
With ThisWorkbook.Worksheets("Sheet1").Shapes(1)
.Left = ThisWorkbook.Windows(1).VisibleRange(2, 2).Left
.Top = ThisWorkbook.Windows(1).VisibleRange(2, 2).Top
End With
End Sub
Sub StartTimedRefresh()
Call ScreenRefresh
eTime = Now + TimeValue("00:00:01")
Application.OnTime eTime, "StartTimedRefresh"
End Sub
Sub StopTimer()
Application.OnTime eTime, "StartTimedRefresh", , False
End Sub
And the following code in Sheet1 (where the shapes are in)
Private Sub Worksheet_Activate()
Call StartTimedRefresh
End Sub
Private Sub Worksheet_Deactivate()
Call StopTimer
End Sub
First create the shape:
Sub Creator()
Dim shp As Shape
Set shp = ActiveSheet.Shapes.AddShape(1, 100, 10, 60, 60)
shp.TextFrame.Characters.Text = "I will follow"
shp.Name = "MyButton"
End Sub
Then in the worksheet code area:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim sh As Shape, r As Range
Set sh = ActiveSheet.Shapes("MyButton")
Set r = ActiveCell
sh.Top = r.Offset(-1, -2).Top
sh.Left = r.Offset(-1, -2).Left
End Sub
If you move the active cell back and forth, the box will move with it.
Note:
This is only demo code. You still need to:
add protection to prevent trying to move the Shape "off-screen"
setting the proper offsets from ActiveCell based on the size of the Shape

Resources