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
Related
I am trying to write a code where sub activates when I select a specific column and specific row but gives me a type mismatch error on the following code:
If Selection.Worksheet.Columns("E:L") And Selection.Worksheet.Rows("16:99999") Then
You will see that the keyword Target always returns the Range Object of the cell that fired the Worksheet_Change Event. So, armed with this knowledge we can now use the Intersect Method to take some action when/if specified cell is changed. For example;
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("E12:L54787")) Is Nothing Then
MsgBox "Hello"
End If
End Sub
Write the code in the corresponding worksheet:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If (Not Intersect(Target, Columns("E:L")) Is Nothing) And _
(Not Intersect(Target, Rows("16:99999")) Is Nothing) Then
Debug.Print Target.Address
End If
End Sub
Selection.Change documentation
Application.Intersect method documentation
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
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.
I am trying to learn a bit of VB and there is an exercise to change a value and check the previous value and if it is different do something. I eventually found a solution I could understand and get to work from : How do I get the old value of a changed cell in Excel VBA? - solution 4.
My code is:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell As Variant
For Each cell In Target
If previousRange.Exists(cell.Address) Then
If Not Application.Intersect(Target, Me.Range("B12:B12")) Is Nothing Then
If previousRange.Item(cell.Address) <> cell.FormulaR1C1 Then
cell.Interior.ColorIndex = 36
End If
End If
End If
Next
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cell As Variant
Set previousRange = Nothing 'not really needed but I like to kill off old references
Set previousRange = CreateObject("Scripting.Dictionary")
For Each cell In Target.Cells
previousRange.Add cell.Address, cell.FormulaR1C1
Next
End Sub
The next exercise was to add a button and perform an action depending on the user's response. So I added:
Private Sub CommandButton2_Click()
Dim currentValue, message As Integer
currentValue = Range("C3").Value
message = MsgBox("Click OK to add 1, cancel to leave", vbOKCancel, "Addition")
If message = 1 Then
Range("C3").Value = currentValue + 1
End If
End Sub
The problem I have is that the button adds one to C3 but then falls over at the If previousRange.Exists(cell.Address) statement on the Worksheet_Change sub.
All the code is defined on Sheet1, but I do not seem to have a previous value generated for my button value(C3). How do I generate the previous value, or what am I missing?
Regards
J
As I seemed to have made things worse I have created a new spreadsheet with just the change events code and nothing else to try and simplify the problem. So the complete code I have now is:
Option Explicit
Dim previousRange As New Dictionary
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cell As Variant
For Each cell In Target
If previousRange.Exists(cell.Address) Then
If Not Application.Intersect(Target, Me.Range("B12:B12")) Is Nothing Then
If previousRange.Item(cell.Address) <> cell.FormulaR1C1 Then
cell.Interior.ColorIndex = 36
End If
End If
End If
Next
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cell As Variant
Set previousRange = Nothing 'not really needed but I like to kill off old references
Set previousRange = CreateObject("Scripting.Dictionary")
For Each cell In Target.Cells
previousRange.Add cell.Address, cell.FormulaR1C1
Next
End Sub
Now if I change the B12 cell, the previousRange As New Dictionary code is highlighted, and a message states "Compile error:User defined type not defined".
This code used to work before I introduced the message box and made a subsequent change. Must be user error. Can you help?
Regards J.
The .Exists method is used on dictionary objects, like the example you've cited. But I don't see where you've declared a dictionary object in your code. Maybe you're missing a declaration statement for it?
Dim previousrange As New Dictionary
Please note that, like the solution you've cited, you'll need to declare this before the sub routine. Also, you'll need to enable the Microsoft Scripting Runtime. Here's how:
In the VBA editor, go to the Tools menu and click on References...
In the Available References list box, scroll down until you see Microsoft Scripting Runtime. Make sure its check box is checked.
Click OK.
Now you're able to use Dictionary objects.
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.