I want to disable cell editing (direct typing into cell) but want to update that cell through code without protecting worksheet
Does anyone have any idea?
In the worksheet's code module:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Range("A1:A10"), Target) Is Nothing Then
Application.EnableEvents = False
Target.ClearContents '// Assuming you want to keep it blank
Application.EnableEvents = True
End If
End Sub
Then in your code whenever you want to change a value, just disable events before hand:
'// Will be deleted
Range("A5").Value = "TEST"
'// Will not be deleted
Application.EnableEvents = False
Range("A5").Value = "TEST AGAIN"
Application.EnableEvents = True
I had a similar issue and found a workaround. For whatever reason I couldn't get my macros to run correctly with the sheets protected so what I did is as a code to Pop up a message box for any cells that I didn't want the user to change. Then I added "Application.DisplayAlerts = False" to the beginning of any codes that needed to modify those cells and reset the alerts back to True at the end of those codes.
Related
I am creating a work order template for use by many users, that is intended to be an add-in that can generate a work order worksheet, where users will have the ability to edit certain information on the sheet and related cells will change accordingly. Currently, the add-in generates the new worksheet and adds the Worksheet_Change code programmatically. This was working correctly originally, until I added a more target cells as fail-safes in case someone accidentally edits the wrong cell. What is happening now, is that the add-in will create the worksheet as intended, but the target cells will not trigger the Worksheet_Change anymore.
I believe that the issue is Application.EnableEvents = False is turning off the Worksheet_Change events, but Application.EnableEvents = True is not turning the events back on afterwards in the code. Application.EnableEvents = True activates the Worksheet_Change again in the Immediate Window, but not in the code. I am fairly certain the code is in the same format it was when working, it just has more target cells. Am I adding Application.EnableEvents = True in the wrong place?
Here is the Worksheet_Change portion of the code.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("D7")) Is Nothing Then
Application.EnableEvents = False
Call addIDValue
Call ChangeIDD7
ElseIf Not Intersect(Target, Range("F7:G7")) Is Nothing Then
Call addCSDValue
ElseIf Not Intersect(Target, Range("C18")) Is Nothing Then
Call addIDValue
Call ChangeIDC18
ElseIf Not Intersect(Target, Range("C20")) Is Nothing Then
Call addCSDValue
Call ChangeCSDC20
Call ChangeG9
'several more ElseIf statements cut for brevity
End If
Application.EnableEvents = True
End Sub
I am trying to creata a VBA that gives me automatic values based on drop down list in a form. The problem is that when I run the macro then it is causing an error and excel stops working. Any help in this case is most welcome.
Private Sub Worksheet_Change(ByVal Target As Range)
If Range("$G$11") = "UD Sheet" Then
Rows("20:25").EntireRow.Hidden = False
Else
Rows("21:25").EntireRow.Hidden = True
End If
If Range("G12").Value = "Flex Tape" Then
Range("B20").Value = "None"
Else
Range("B20").Value = ""
End If
exitHandler:
Application.EnableEvents = True
Exit Sub
End Sub
First thing first, in your code, no need to put an Exit Sub before the End Sub.
The code will end after that line so this is a redundancy.
The next thing that you need to understand is that the Change Event will keep triggering if you will not disable it explicitly. So it means that when you hide a row on that Sheet, the Change Event will keep on happening since there will be changes that will happen on the Sheet. i.e. (Hiding Rows).
To do that you need to disable the EventsListeners of the application using the Application.EnableEvents = False. So the application can do a single thing based on that first event.
The next thing that you need to keep in mind is to track where the Changes occur and fire your program. Target is a Range Object that will return the Range where the specific change occurs on the Sheet.
In order to do that, you need to validate if you need to trigger the routine based on the target using the Intersect function.
The whole code is as follows:
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Not Intersect(Target, Range("G11")) Is Nothing Then
If Range("$G$11") = "UD Sheet" Then
Rows("20:25").EntireRow.Hidden = False
Else
Rows("21:25").EntireRow.Hidden = True
End If
End If
If Not Intersect(Target, Range("G12")) Is Nothing Then
If Range("G12").Value = "Flex Tape" Then
Range("B20").Value = "None"
Else
Range("B20").Value = ""
End If
End If
Application.EnableEvents = True
End Sub
I'm trying to clear the contents of a merged cell based on the selection from a data validation list (the list is also in merged cells). And yes, "Don't use merged cells!" is great advice (I prefer "center across") but would complicate things in this case. I've tried naming the merged cells, using "MergeArea," etc. but I haven't been successful in finding a solution yet.
Below is the latest iteration I have. Please note I've been trying to make just one selection ("Yes." in this case) work before adding in the second selection (or "blank" in this case).
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Range("Max_Advance").MergeArea Then
If Range.Validation.Type = 2 Then
Range("Days_Needed").MergeArea.ClearContents
End If
End If
exitHandler:
Application.EnableEvents = True
Exit Sub
End Sub
Can anyone help? I've also attached a picture to visually show what I'm working with:
Does this work for you?
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address(0, 0) = "A2" Then
On Error GoTo exitHandler
Application.EnableEvents = False
If LCase(Target.Value) <> "no. please enter." Then
Range("Days_Needed").MergeArea.ClearContents
End If
End If
exitHandler:
Application.EnableEvents = True
Exit Sub
End Sub
You can usually clear the contents of a merged cell by treating it as if it was the first cell in the merge.
for example:
Range("A2")=""
I'm trying to capture the worksheet change event when a table heading is cleared by the user.
Private Sub Worksheet_Change(ByVal Target As Range)
application.EnableEvents = False
If Not Intersect(Target, Me.ListObjects("Table1").HeaderRowRange) Is Nothing Then
msgbox "Hello"
end if
application.EnableEvents = True
End Sub
If the user presses "delete" to clear a non-default heading name on the table, Excel automatically replaces the blank heading with the default heading name (eg. "Column1"). This seems to cause the worksheet change event to run multiple times. I'd like to figure out a way to have this event run only once when the user clears the a heading.
Any help is greatly appreciated.
The easiest workaround for this is to add an assertion at the beginning of your event, that checks that the target cell does not already contain a default column name.
I would do this with a simple if and like statement, which catches when a heading begins with "Column" and exits the event using Exit Sub. You could do all of this in one simple line of code. Something like...
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.value Like "Column*" Then Exit Sub
application.EnableEvents = False
If Not Intersect(Target, Me.ListObjects("Table1").HeaderRowRange) Is Nothing Then
msgbox "Hello"
end if
application.EnableEvents = True
End Sub
This code is admittedly untested but it should provide you with a good base to start from.
Using Excel 2010 I am editing an existing unprotected workbook and have created EntireColumn.Hidden and EntireRow.Hidden in commands in the Worksheet_Change() event to fire when a Data Validation cell is changed, but they don't work.
Private Sub Worksheet_Change(ByVal Target As Range)
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
If Not Intersect(Target, Range("$C$2")) Is Nothing Then
Select Case Target.Value
Case "NO"
MsgBox "You just changed to HIDE" '<= Proves it fires
Range("$C$3").Value = "Invisible" '<= Does change cell
Columns("N:O").EntireColumn.Hidden = True '<= Doesn't hide
Case "YES"
MsgBox "You just changed to UNHIDE" '<= Proves it fires
Range("$C$3").Value = "Visible" '<= Does change cell
Columns("N:O").EntireColumn.Hidden = False '<= Doesn't unhide
End Select
End If
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
The event is firing as I have MsgBoxes to prove it. I can change cell values etc., but not the hiding/unhiding of the column/row.
I've copied my code to a new book and it works. So I copied it back into the original book but as a fresh, blank sheet and it works. It still doesn't work in the original, sizable sheet.
When I copied this into a simple macro it does work as required, hiding the correct columns, but at the push of a button:
Sub HideThem()
Columns("N:O").EntireColumn.Hidden = True '<= DOES work
End Sub
I need this to update automatically based on the value of a single cell. I've even tried to call this mini Sub from within the Worksheet_Change() event but that didn't work either.
Are there any known conflicts with other commands/events, on-sheet buttons, images, merged cells etc. that could be preventing the columns/rows from hiding?
I tried to use a CheckBox instead of a YES/NO Data Validation cell to fire the code (as that could be acceptable) but when I try to insert an ActiveX CheckBox it says Cannot insert object, even in a brand new blank book. Could this be a related problem?
I suppose you have a drop-down list in cell C3 with two items, viz "Visible" and "Invisible".
The following code will hide Columns N and O when you change the value of Range C3 from blank / "Visible" to "Invisible". Prior to this action, you will have to read the message and click OK. Changing from "Invisible" to "Visible" will present you with a message box. Click OK and see the hidden columns reveal themselves.
Private Sub Worksheet_Change(ByVal Target As Range)
If Range("C3") = "Invisible" Then
MsgBox ("You just changed to HIDE")
Columns(14).Hidden = True
Columns(15).Hidden = True
Else
If Range("C3") = "Visible" Then
MsgBox ("You just changed to UNHIDE")
Columns(14).Hidden = False
Columns(15).Hidden = False
End If
End If
End Sub