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.
Related
I was knowing before how create that code in case of determining a specific array to implement a function in it:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, Range("A1:O7000")) Is Nothing Then
MsgBox "Hi"
End If
End Sub
So Intersect here works only when I write inside Argument2 Range function.
I don't want to determine whole that array. When I want to develop this code by this shape:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim SafeTbl As ListObject
Set SafeTbl = ListObjects("Safe")
If Not Intersect(Target, SafeTbl.Range.Address) Is Nothing Then
MsgBox "Hi"
End If
End Sub
I find this Type mismatch compile error:
I don't know why this error exists. While I see that my development is making same as previous code does. As this code is determining only array has data.
As suggested in the comments, .Address is a string. The Intersect method requires ranges as the parameters, not the text of the range address, which you are currently providing.
The Type mismatch compile error is telling you that the "variable or property isn't of the correct type" (https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/type-mismatch-error-13)
Microsoft says:
[Application.Intersect method (Excel)] Returns a Range object that
represents the rectangular intersection of two or more ranges.
To be explicit, this means your code needs changing to this:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim SafeTbl As ListObject
Set SafeTbl = ListObjects("Safe")
If Not Intersect(Target, SafeTbl.Range) Is Nothing Then
MsgBox "Hi"
End If
End Sub
More can be read about the Intersect method here: https://learn.microsoft.com/en-us/office/vba/api/excel.application.intersect
And also more about the Range property here: https://learn.microsoft.com/en-us/office/vba/api/excel.range.range
Update
As #BigBen correctly points out, in your case, we are actually referring to the ListObject.Range property, so the further information on this is here: https://learn.microsoft.com/en-us/office/vba/api/excel.listobject.range
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
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.
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.