This is probably very basic, but I have tried so many things and the always give errors.
Basically what I'm trying to do is run a procedure every time a cell gets changed in Excel. So I'm using Sub Worksheet_Change(ByVal Target As Range).
All works well, but in this procedure, I'm calling another sub procedure several times.
I want to reuse the 'Target' value in this procedure, but for some reason, I can't find how to do it. I tried placing 'Public rTarget As Range' and do a 'rTarget = Target' at the beginning of the procedure. But the rTarget stays empty when I call the sub procedure.
How do I make this work?
I'm now adding Target as one of the variables to to subroutine, but that just looks stupid.
Thanks!
Private Sub Worksheet_Change(ByVal Target As Range)
MySub Target
End Sub
Sub MySub(ByVal Target As Range)
' Your sub code goes here and can work with the Target Range from the Worksheet_Change Event
End Sub
Passing Target as a variable is how you should do it. You want to keep your variables in the tightest scope possible and passing them as arguments is the tightest.
If you're passing the variable to a bunch of different procedures in the same module, it may make sense to have a module-level variable. That looks like this
Private mrTarget As Range
Private Sub Worksheet_Change(ByVal Target As Range)
Set mrTarget = Target
MySub
End Sub
Private Sub MySub()
Debug.Print mrTarget.Address
End Sub
Based on your questions, it's just one sub that gets called repeatedly. In that case, I would stick with passing it as an argument.
Related
I have 2 different modules. One is triggering the other. Like that;
Private Sub Worksheet_Change(ByVal TarGet As Range)
If Not Intersect(TarGet, Range("o7:o1000")) Is Nothing Then
Call dograma
End If
End Sub
And the other one is starting like that:
Sub dograma()
Txt = TarGet.Value
I get an error because "TarGet" expression not defined in this sub. But I would like to use the same variable for both subs. Can I synchronize them?
In second sub i changed name like that
Sub dograma(ByVal TarGet As Range)
and
In the first module I changed
Call Dograma
with
Call Dograma (TarGet)
It works well.
I have the following worksheet function saved in the Sheet1 (DataInput) module of VBA
Sub worksheet_change(ByVal target As Range)
Set target = Range("F67")
If target.Value = "YES" Then
Call ThisWorkbook.Red_Macro_Text
End If
End Sub
This code calls the following code in ThisWorkbook
Public Sub Red_Macro_Text()
ThisWorkbook.Worksheets("DataInput").Range("B68").Value2 = ThisWorkbook.Worksheets("Text").Range("B3").Value2
End Sub
The purpose of the code is as follows:
The code uses an event trigger to watch for changes to worksheet ‘datainput’ cell F67.
Whenever the user selects ‘YES’ from a drop down menu in cell F67 it calls the subroutine in ThisWorkbook.
The code uses the range function to assign the value of 'text' worksheet B3 into 'datainput' worksheet B68 cell.
The trigger event does call the code and the content of B3 does get transferred to B68 however following this I then get the error message:
Run-time error ‘-2147417848 (80010108)’: Automation error The object
invoked has disconnected from its clients.
Please note I do not want to use an IF statement in excel to achieve this as I am trying to automate the process in VBA.
I have been searching for a solution to this problem for some time without success.
Does anyone know how to solve this problem as I have reached the limit of my understanding!
All help is appreciated
It doesn't make sense to Set target = Range("F67") because it is already retrieved as parameter ByVal target As Range
If you want to run the code only if F67 changes use the following instead:
Sub worksheet_change(ByVal Target As Range)
If Not Intersect(Target, Target.Parent.Range("F67")) Is Nothing Then
If Target.Parent.Range("F67").Value = "YES" Then
ThisWorkbook.Red_Macro_Text
End If
End If
End Sub
Note that Call is not needed to call a macro.
Try
Sub worksheet_change(ByVal Target As Range)
If Target.Address = Range("F67").Address Then
If Target.Value = "YES" Then
Call ThisWorkbook.Red_Macro_Text
End If
End If
End Sub
I have a range of values in a column which I am targeting.
Once any of the values in that range changes, it is supposed to call a macro.
The macro I am calling works but my change event is not getting recognized. Is there something wrong with my code?
My change even macro is located on the sheet where the change event is happening:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$H$5:$H$32" Then
Call SetAxes
End If
End Sub
Do I need to be more specific with the range address?
Target.Address = "$H$5:$H$32" will only be True if that entire range changes at once.
To trap changes to one or more cells within that range, use Application.Intersect like this:
If Not Application.Intersect(Target, Range("$H$5:$H$32")) Is Nothing Then
I simply used worksheet_calculate and called the function when anything changes on the worksheet.
All the macro it is calling does is set the axes, so I don't mind if it runs repeatedly.
Private Sub Worksheet_Calculate()
Call SetAxes
End Sub
as a workaround, you could add a function:
Function FakeChange() As Integer
SetAxes
FakeChange = 0
End Function
and add behind your formulas in "$H$5:$H$32" +Fakechange()
like: ='your formula'+ FakeChange()
This function will be triggered when the results of your formulas are changed
How to pass on the Target to another macro in Excel events? For just the elegant purpose, I would like to use the following structure, which does not work now.
Private Sub Worksheet_Change(ByVal Target As Range)
GoToAnotherMacro(Target)
End Sub
Sub GoToAnotherMacro(Target)
'here my code where I can use Target i.e:
MsgBox "value: " & Target.Value
End Sub
I would suggest the use of a global variable:
1) Define a global variable:
Dim RangeSupp As Range
2) In your procedure, pass the local Target to your global variable
Private Sub Worksheet_Change(ByVal Target As Range)
Set RangeSupp = Target
GoToAnotherMacro RangeSupp
End Sub
3) Enjoy your target in your other macro
Sub GoToAnotherMacro(Target As Range)
MsgBox Target.Value
End Sub
NOTE: Global variables are put on top of all the code, outside any other Function or Sub. The global variable is preserved in the stack even outside the single scope of the macro. That is the reason why you will be able to pass a global variable from a macro to the other. On the other hand, now you're not able (you get "Object required error") because the Target object, once outside its scope in Worksheet_Change, is removed from the stack so it gets back to its default value (Nothing), causing the problem you have in your above code.
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.