I found code online as an example that I have tweaked to show or hide specific rows depending on the selection I choose within a dropdown in my Excel file.
The macro is not working no matter what I try.
My code is as follows (also attached screenshot of rows under question 2 (2a - 2d) that are not showing/hiding)
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$F$13" Then
If Range("F13").Value = "Yes" Then
Rows("14:17").EntireRow.Hidden = False
End If
If Range("F13").Value = "No" Then
Rows("14:17").EntireRow.Hidden = True
End If
If Range("F13").Value = " " Then
Rows("14:17").EntireRow.Hidden = True
End If
End Sub
This is a good example of properly intending your code helping you identify an issue. You're missing an End IF statement. Try this:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$F$13" Then
If Range("F13").Value = "Yes" Then
Rows("14:17").EntireRow.Hidden = False
End If
If Range("F13").Value = "No" Then
Rows("14:17").EntireRow.Hidden = True
End If
If Range("F13").Value = " " Then
Rows("14:17").EntireRow.Hidden = True
End If
End If
End Sub
You may also want to use:
If Range("F13").Value = ""
instead of
If Range("F13").Value = " "
There is an End If missing. I assume the value of the target cell (F13) needs to be tested for it's value. If the value is "Yes", it should unhide row 14:17, if it is " " (spacebar) it should hide them and if it is "No" is should hide them as well. Other values will not affect the hiding/unhiding of the rows.
There should be a second End If before End Sub, so that all the if-statements above are wrapped within the Address check.
Also note that this code should be placed in the worksheet itself, since you want to hook into the Worksheet_Change event.
Try this in a worksheet module:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$F$13" Then 'Check if the changed value is indeed in F13
If Target.Value = "Yes" Then
ActiveSheet.Rows("14:17").EntireRow.Hidden = False 'Show the rows if the value is Yes
ElseIf Target.Value = "No" Then
ActiveSheet.Rows("14:17").EntireRow.Hidden = True 'Hide them when it's No
ElseIf Target.Value = " " Then
ActiveSheet.Rows("14:17").EntireRow.Hidden = True 'Or space
End If
End If
End Sub
Other remarks:
Instead of ActiveSheet you can also use Me (Me.Rows...) In this scenario they probably do the same. However, if you change the value on a worksheet from another worksheet (e.g. formula that recalculates), Me will reference the changed worksheet that fires the event, whereas activeworksheet will affect the currently active sheet.
Use Target instead of referencing the Range again. Target is a range object that is already in memory. Hence execution will be faster compared to accessing the worksheet again.
Related
I have a large VBA macro which consists of one large Private Sub Worksheet_Change(ByVal Target As Range).
It first gives me the procedure too large error as it is really big.
When I tried to break it into 3 Private Sub Worksheet_Change(ByVal Target As Range).
this error shows up:
ambiguous name detected worksheet_change
any clues I can work around these 2 errors?
thanks in advance
here are my codes, the actual codes have tonnes of conditions and text check for each target address
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = [rng_opt1].Address Then
If [rng_opt1] = "x" Then
If [rng1_1] = "z" then
[rng1_1] = " "
End if
End If
End if
End sub
thanks to #urdearboy, I got it solved, my final codes is like this (much simplified version). it's tricky and took me a while as my target has defined name
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Whoa
Application.EnableEvents = False
If Target.Address = [rng_opt1].Address Then
Call Opt1(Target)
ElseIf Target.Address = [rng1_1].Address Then
Call Opt11(Target)
End if
LetsContinue:
Application.EnableEvents = True
Exit Sub
Whoa:
MsgBox Err.Description
Resume LetsContinue
End Sub
Sub Opt1(Target As Range)
If Target.Address = [rng_opt1].Address Then
If [rng_opt1] = "x" Or [rng_opt1] = "y" Then
If [rng1_1] = "z"
[rng1_1] = " "
End If
End if
End if
End Sub
Sub Opt11(Target As Range)
If Target.Address = [rng1_1].Address Then
If [rng1_1] = " " Then
If [rng1_2] = " " And [rng1_3] = " " And [rng1_4] = " " Then
[rng1_1] = "y"
[rng1_2] = "x"
End If
End If
End if
End sub
You can only have one WorkSheet_Change event on a worksheet which is why you are getting the Ambiguous Name Detected error.
If your code is too long, try to create your actions in a Sub and then call those subs given certain criteria. This way, you can limit your WorkSheet_Change code to strictly evaluate the Target.
In you WorkSheet_Change code you can have something like:
If Target.Value = “x” Then
Call SubX
ElseIF Target.Value = “y” Then
Call SubY
ElseIF Target.Value = “z” Then
Call SubZ
End IF
SubX ()
‘Do Something
End Sub
SubY ()
‘Do Something
End Sub
SubZ ()
‘Do Something
End Sub
Note:
You will need to disable events before you make any physical change to your sheet otherwise you will find yourself in a infinite loop and crash your instance of excel. Use the below method to avoid this issue:
Application.EnableEvents = False
‘Physical changes to worksheet
Application.EnableEvents = True
My worksheet is set up with data validation dropdowns and I am wanting a macro to ONLY trigger when the value of the cell is changed from another value in the dropdown, not from the default "empty" value.
Here is what I am trying to use:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 5 Then
If IsEmpty(Target.Value) = True Then
MsgBox "Test1"
Else
MsgBox "Test2"
End If
End If
exitHandler:
Application.EnableEvents = True
Exit Sub
End Sub
My problem is that this "IsEmpty" command is reading the cell AFTER the selection not before. I want it to read what the cells value was BEFORE the selection not after.
How can I do this?
Example approach:
Const COL_CHECK As Long = 5
Private oldVal
Private Sub Worksheet_Change(ByVal Target As Range)
Dim c As Range
Set c = Target.Cells(1) '<< in case multiple cells are changed...
If c.Column = COL_CHECK Then
If oldVal <> "" Then
Debug.Print "changed from non-blank"
Else
Debug.Print "changed from blank"
End If
End If
exitHandler:
Application.EnableEvents = True
Exit Sub
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim c As Range
Set c = Target.Cells(1)
oldVal = IIf(c.Column = COL_CHECK, c.Value, "")
Debug.Print "oldVal=" & oldVal
End Sub
Another approach:
This will need one cell per validation-dropdown:
Function ValChange(Cell2Follow As Range) As String
ValChange = ""
If Len(Application.Caller.Text) = 0 Then Exit Function
If Application.Caller.Text = Cell2Follow.Text Then Exit Function
MsgBox "value of the cell is changed from another value in the dropdown" & vbLf & "not from the default 'empty' value"
End Function
in a different cell, assumed the dropdown is in E6:
=E6&ValChange(E6)
application.caller.text will be the old value
(calculation must be automatic)
I am looking for way to keep a formula in a cell every time another cell is active.
Private Sub Worksheet_Change(ByVal Target As Range)
If ActiveSheet.Range("AL2").Value = 1 Then
ActiveSheet.Range("AK14").Value = ActiveSheet.Range("AL8").Value
Else
End If
End Sub
So if Cell AL2 is equal to 1 (so my desired active cell) I want to have a certain value in cell AK14.
If cell AL2 is NOT equal to 1 I want to just keep value in AK14 unchanged (so for example somebody can overwrite it).
At the moment Excel seems to get lost with the second part: if AL2 = 0 and I am getting an error.
If I need two conditions, do I just put another If?
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Range("AL2").Value = 1 Then Range("F11").Value = Range("AK7").Value
Application.EnableEvents = True
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Range("AL2").Value = 2 Then Range("J11").Value = Range("AL7").Value
Application.EnableEvents = True
End Sub
so I want to have those two macros..
When you change value in a cell, in a Worksheet_Change event, you should disable the events. Otherwise, it starts calling itself:
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Range("AL2").Value = 1 Then Range("AK14").Value = Range("AL8").Value
Application.EnableEvents = True
End Sub
Then, as a next step it is really a good practice to use Error-catcher here with the .EnableEvents:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Worksheet_Change_Error
Application.EnableEvents = False
If Range("AL2").Value = 1 Then Range("AK14").Value = Range("AL8").Value
Application.EnableEvents = True
On Error GoTo 0
Exit Sub
Worksheet_Change_Error:
Debug.Print "Error " & Err.Number & " (" & Err.Description & ") "
Application.EnableEvents = True
End Sub
I want to lock cell B20 and write "1" on it if I choose a certain option ("T") on the dropdown of B18. If I choose any other option, I want to be able to fill it normally without any limitations. Here is the best code I tried:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim ws As Worksheet
Set ws = ActiveSheet
If Target.Address = "$B$18" Then
ws.Unprotect
Application.EnableEvents = False
Target.Offset(1).Locked = Target.Value = "T"
If Target.Value = "T" Then
Target.Offset(1).Value = 1
Else
If Target.Offset(1).Value = 1 Then Target.Offset.Value = ""
End If
Application.EnableEvents = True
ws.Protect
End If
End Sub
This code is doing exactly what I want but its performing this on the cell B19 instead of B20.
Can somebody help me please?
There is a bunch of code and text all saying different things in your question, so I based this code on your comment and the text of your question.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$B$18" Then
ws.Unprotect
Application.EnableEvents = False
Target.Offset(2).Locked = Target.Value = "T"
If Target.Value = "T" Then
Target.Offset(2).Value = 1
Else
If Target.Offset(2).Value = 1 Then Target.Offset.Value = ""
End If
Application.EnableEvents = True
ws.Protect
End If
End Sub
I have vba code which pops up msg box if the entered value is zero. if the user later wants to change the zero to some other number it will still pops up the msg box before it allows to edit the zero to some other number.
I don’t want the msgbox pop up if user is changing the existing value.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Intersect(Target, Range("b4:af18")) Is Nothing Then
If Target.Value = 0 Then
Application.EnableEvents = True
MsgBox "This is it", vbApplicationModal, "Scikess/Holiday"
End If
End If
Application.EnableEvents = True
End Sub
I believe you are describing a situation where the user taps the delete key before typing in a new answer. In that case the blank cell has a numerical value of zero and you are getting a false positive on the check to see if the user typed in a zero.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("b4:af18")) Is Nothing Then
On Error GoTo bm_Safe_Exit
Dim trgt As Range
Application.EnableEvents = False
For Each trgt In Intersect(Target, Range("b4:af18"))
If trgt.Value = 0 And trgt.Text = "0" Then
MsgBox "This is it" & Chr(10) & trgt.Address(0, 0) & " cannot be zero.", _
vbApplicationModal, "Scikess/Holiday"
Application.Undo
trgt.Activate
Exit For
End If
Next trgt
End If
bm_Safe_Exit:
Application.EnableEvents = True
End Sub
I've attempted to have the code run when more than a single Target is involved (e.g. a paste or fill operation) but this makes the Application.Undo difficult to keep the other valid entries. Leave a comment on this behavior if it is unsuitable.
It also wasn;t clear on what range you wanted this to react on. You seem to have missed the Not in your Intersect method, making it react on any cell that wasn't in the range. I've adjusted above to include the range you specified, not exclude it.