excel/VBA pass a sheetname to a function - excel

i have few sheet, and a need for once of it that a specific cell (A1) is equal "1" the label color become green once the change their value.
I declare in a ThisWorkBook the following function:
Public Function ColorLabel(LabelName)
Set Foglio = Sheets(LabelName)
Set Target = Foglio.Range("A1")
If Target = "1" Then
Foglio.Tab.ColorIndex = 4
Else
Foglio.Tab.ColorIndex = xlNone
end if
End Function
So, in every sheet i define the following code
Private function Worksheet_Change(ByVal Target As Range)
ColorLabel(ActiveSheet.CodeName)
end function
but I get the following error
Compilation error. Expected variable or routine and not form
What's wrong?
Someone help me?
Thanks!

Your Public Function ColorLabel(LabelName) should be placed in a Module, not inside one of the Sheets or the Workbook. Usualy we place there code that is related only to Sheets events or Workbook events.
see image for Public Function ColorLabel(LabelName) code
Your Private function Worksheet_Change(ByVal Target As Range) should be in the Workbook_SheetChange event (in the Workbook module):
Code:
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
ColorLabel (Sh.Name)
End Sub
You could improve your code, by not calling ColorLabel function on every change made to any cell in any sheet, by checking if the Target is inside Range("A1"), see code below:
Improved Code:
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
' call the ColorLabel function only if value in Cell A1 was modified
If Not Intersect(Target, Range("A1")) Is Nothing Then
ColorLabel (Sh.Name)
End If
End Sub

If the function is defined in the ThisWorkbook module, you should call it this way:
ThisWorkbook.ColorLabel Me.Name
and by the way, as it is written, ColorLabel shoud be a Sub not a function (it does not return anything).
However, better design would be:
move the sub to an independent code module
or
rename the sub into an event handler using Workbook_SheetChange

Why do you need to pass the name of the worksheet at all? Just pass a reference to the worksheet itself:
Public Function ColorLabel(Foglio As Worksheet)
Dim Target As Range
Set Target = Foglio.Range("A1")
If Target.Value = "1" Then
Foglio.Tab.ColorIndex = 4
Else
Foglio.Tab.ColorIndex = xlNone
End If
End Function
'If this is the event handler you want...
Private Function Worksheet_Change(ByVal Target As Range)
ColorLabel Me
End Function
'Or in ThisWorkbook:
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
ColorLabel Sh
End Sub

Related

How to run a macro when a cell updates through refreshing of data from web?

When the column is refreshing nothing is happening but when I go to the cell and change the value then it is changing.
I want when cells update through refresh it should run.
The column updates but the code doesn't trigger the macro.
Also tried Worksheet_Calculate().
The column is linked with online stock data from NSE website.
Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("B:B")) Is Nothing Then
MsgBox "Cell Value Changed"
Call MyMacro()
End If
End Sub
On internet just told to use Worksheet_Calculate().
Also if trying to update the cell which is equal to a cell in Range("B:B"), the value changes but macro doesn't trigger.
Maybe give this a try by using Workbook_SheetChange instead of Worksheet_Change
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("B:B")) Is Nothing Then
MsgBox "Cell Value Changed"
Call MyMacro()
End If
End Sub
Note that you need to put your code in ThisWorkbook and not your module
Edit : to test the Answer :
Sub TryMe()
For i = 1 To 100
Cells(2, 2).Value = i
Next
End Sub
TryMe Should be added inside a module like below
Workbook_SheetChange hould be added inside ThisWorkbook like below
When we execute test module we should have stuff like this:
and so on..
EDIT 2 If Value are changed by formula :
Give this a try :
This code should be placed in the sheet you are using (in my exemple Sheet1)
Private Sub Worksheet_Calculate()
Dim rng As Range
Set rng = Range("B:B")
If Not Intersect(rng, Range("B:B")) Is Nothing Then
MsgBox "Cell Value Changed"
End If
End Sub
In a Module execute this code once :
Sub TryMe()
ActiveWorkbook.RefreshAll
Application.Calculation = xlAutomatic
End Sub
then this should work
You can use events of QueryTable object behind the table linked to a web source. To do that, you first need to create a class module. Let's call it clsQryTebleEvents. In that module place a WithEvents variable of type Excel.QueryTable and set it to the QueryTable for which you want to capture events. Here's the code for clsQryTableEvents:
Option Explicit
Private WithEvents qryTable As Excel.QueryTable
Private Sub Class_Initialize()
'QueryTable connected to a webpage is on Sheet1, and it's the only table on that sheet, so we can access it with ListObjects(1)
Set qryTable = Sheet1.ListObjects(1).QueryTable
End Sub
Private Sub Class_Terminate()
'Free Memory
Set qryTable = Nothing
End Sub
'You can use other events as well
Private Sub qryTable_BeforeRefresh(Cancel As Boolean)
MsgBox "Refresh is about to start!", vbInformation
End Sub
Next, you need to initialize a variable of this class. You can declare a Public variable inside a standard module and the use Workbook_Open event to instantiate it. Code in a standard module:
Option Explicit
Public objQryTable As clsQryTableEvents
Code in ThisWorkbook:
Option Explicit
Private Sub Workbook_Open()
Set objQryTable = New clsQryTableEvents
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
'Free memory
Set objQryTable = Nothing
End Sub
All done! Next time you open the workbook, the objQryTable will be initialised and will start listening to refresh events.

Excel : How do I call the "active cell" to a cell

I have Excel 2013
Currently i have a code that takes any cell i click on and shows its contents to another cell as well.
My digging through the internet came up with the code below.
How do i call this to a cell with a custom formula instead of editing the code every time i want to change the location (b15) in this case?
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
If Not Intersect(Target, ActiveSheet.UsedRange) Is Nothing Then
Range("B15").Value = Target.Value
End If
End Sub
Thank you in advance.
In a standard module include:
Public Function ShowMe() As Variant
Application.Volatile
ShowMe = ActiveCell.Value
End Function
and in the worksheet code area include:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Application.Calculate
End Sub

How do I pass the contents of the "Target" range in a "Worksheet_SelectionChange event to a sub?

Sheet 1 of my workbook contains (besides other data) a list of the other worksheets in column A. I wish to be able to click on any cell in column A5:A50 and go to the appropriate worksheet listed in that cell. My Sheet1 code is:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, Me.Range("A5:A50")) Is Nothing Then SelectWorksheet
End Sub
and Module2 is:
Sub SelectWorksheet()
Dim strName As String
strName = Sheet1.Range("Target").Text (Error occurrs here: "Method 'Range' of object 'Worksheet' failed")
Sheets(strName).Select
End Sub
How do I get this to work as I expect? I know I could just click on the appropriate worksheet tab but I'm trying to learn how to code in VBA. Thanks. By the way, how do I get my post to show the code as typed in the question box?
Like this. You probably want to use the _SelectionChange event instead of the _Change event. Or you may find it necessary to use both events to trigger it. In any case here is how you pass the variable to another subroutine/module:
Sub Worksheet_SelectionChange(byVal Target as Range)
'Some code...
'
Call OtherMacro(Target)
'
End Sub
And then in your other macro, declare a range variable as required argument, like so:
Sub SelectWorksheet(rng as Range)
'
Dim strName as String
' at this point you can work with the "rng" variable, because it's been received from the other subroutine
strName = rng.Value
Sheets(strName).Activate
'
End Sub
You would need to add additional test to make sure user has not selected multiple cells, etc., but this should get you started.
Why not pass the sheet name from the cell to the sub?
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, Me.Range("A5:A50")) Is Nothing _
And Target.Cells.Count = 1 Then SelectWorksheet (Target.Value)
End Sub
Sub SelectWorksheet(strName As String)
Sheets(strName).Select
End Sub
I've also done a check to make sure that only one cell is in the selection.

VBA Excel Worksheet Change Autofit Rows

I have this code in a standard module, which works fine:
Public Sub AutofitRows()
ThisWorkbook.Worksheets("Data").Cells.EntireRow.AutoFit
End Sub
Then I have this code in the Data worksheet module, which doesn't autofit all the rows for some reason:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$B$3" Then
Call AutofitRows
End If
End Sub
Can somebody please explain how to correct this?
Thanks.
Try below code :
Public Sub AutofitRows()
Dim rng As Range
Set rng = ThisWorkbook.Worksheets("Data").Rows("3:3")
rng.AutoFit
End Sub
Assuming your below code resides on Worksheets("Data").Also the procedure will be called when value in cell B3 will change.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$B$3" Then
Call AutofitRows
End If
End Sub

Excel Worksheet_Change Event not working

I am trying to write a macro where changing any column
should automatically save worksheet.
My Excel sheet expands till G25.
I tried this but its not working:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("G25")) Is Nothing Then
ActiveWorkbook.Save
End Sub
I have save it under ThisWorkBook.
Any help is appreciated.
Under ThisWorkbook that handler is called Workbook_SheetChange and it accepts two arguments, Sh (of type Object) and Target (a Range). So, your code won't work there.
If you put your code in the sheet you want (Sheet1, for instance) instead of in the ThisWorkbook, put the End If and change the range to "A1:G25" (representing a square from row 1 column A to row 25 column 25), it should work.
This did:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("A1:G25")) Is Nothing Then
MsgBox "changed"
End If
End Sub
For completeness, under ThisWorkbook, this will work:
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("A1:G25")) Is Nothing Then
MsgBox "changed"
End If
End Sub
The other common reason why an Event doesn't work is that EnableEvents has been set to False
I would code your problem like this as
typically you need to work with the range of interest that is being tested. So creating a variable rng1 below serves both as an early exit point, and a range object to work with. On a sheet event Target.Worksheet.Range("A1:G25") will work but it is lengthy for it's actual use
If you do have a range to manipulate then making any further changes to the sheet will trigger a recalling of the Change event and so on, which can cause Excel to crash. So it is best to disable further Events, run your code, then re-enable Events on exit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng1 As Range
Set rng1 = Intersect(Target, Range("A1:G25"))
If rng1 Is Nothing Then Exit Sub
Application.EnableEvents = False
'work with rng1
Application.EnableEvents = True
End Sub

Resources