Restricting the user to delete the cell contents - excel

Is there's any way to restrict the user from deleting the cell contents without using the protect method of excel. I have this code:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet1")
If Not Intersect(Target, Range("C21:D" & ws.Range("C" & ws.Rows.Count).End(xlUp).Row)) Is Nothing Then
Cancel = True
MsgBox "You are not allowed to edit!", vbCritical + vbOKOnly
EndIf
End sub
But this only disallows the editing of the cell contents. I want make a function that would disallow the editing and deleting the data in a cell without using the protect method. Thanks!

Without lock and unlock, you can use this.
We have there one global variable to store selection value (to preserve beforechange state). Function SelectionChange, updating value of current cell, so we can restore cell value after users try.
Sub worksheet_change just controling, if user targeting specified row and column (can be adjusted for whole range), and if he try to change value, he is prompted and value is set back.
Dim prevValue As Variant
Private Sub worksheet_SelectionChange(ByVal target As Range)
prevValue = target.Value
End Sub
Private Sub worksheet_change(ByVal target As Range)
If target.Row = 5 And target.Column = 5 Then
If target.Value <> prevValue Then
target.Value = prevValue
MsgBox "You are not allowed to edit!", vbCritical + vbOKOnly
End If
End If
End Sub
edit: disable editing every cell which is not empty
Private Sub worksheet_change(ByVal target As Range)
If prevValue <> "" Then
If target.Value <> prevValue Then
target.Value = prevValue
MsgBox "You are not allowed to edit!", vbCritical + vbOKOnly
End If
End If
End Sub

Try my idea. Copy and paste these codes into the module of the sheet where the protected range is located. In my case it was called "Arkusz1". The protected range is "A1:A10".
Private Sub Worksheet_Change(ByVal Target As Range)
For Each cell In Range("A1:A10")
If cell.Text <> Sheets("hidden").Cells(cell.Row, cell.Column) Then
Call Undoing
End If
Next cell
End Sub
Private Sub Undoing()
Application.EnableEvents = False
Application.Undo
Application.EnableEvents = True
End Sub
In the "This_worksheet" module copy and paste this code:
Private Sub Workbook_Open()
Sheets.Add
ActiveSheet.Name = "hidden"
Sheets("Arkusz1").Range("A1:A10").Copy
Sheets("hidden").Select
ActiveSheet.Paste
Sheets("hidden").Select
ActiveWindow.SelectedSheets.Visible = False
End Sub
Private Sub Workbook_Close()
Sheets("hidden").Visible = True
Sheets("hidden").Delete
End Sub
You will have to change the name of the sheet from "Arkusz1" to "Sheet1" or any other name Your sheet has got.
The idea is as follows. Upon the opening of the workbook the application creates a hidden spreadsheet into which it copies the contents of protected cells. For some technical reasons I had to hide the sheet after the copy operation, otherwise it did not work on my computer. Then, any change of the sheet "Arkusz1" triggers the event which compares the contents of the protected range with the same range in the hidden sheet.
If there are any differences the application undoes the last action of the user.
Undoing has to be done when event handling by Excel is turned off, because undoing a previous action is also an event of changing the sheet and we would cause a cascade of events - every undo operation would trigger the event "worksheet_change" and it would never stop getting activated.
Application.EnableEvents = False
Application.Undo
Application.EnableEvents = True

Related

How to run this function in excel using vba

Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = Range("B12").Address Then
Application.EnableEvents = False
Dim sOldValue As String, sNewValue As String
sNewValue = Target.Value
Application.Undo
Dim rOld As Range
Set rOld = Range("A1:E1").Value
Target.Value = sNewValue
Range("A15:E15").Value = rOld.Value
Application.EnableEvents = True
End If
End Sub
How to run this function, can you please call this function?
Create a button, add in the following code, you might need to change your code from Private to Public
`Private Sub CommandButton1_Click()
Call Worksheet_Change
End Sub`
The code you posted is for the Worksheet.Change event. The event occurs when cells on the worksheet are changed by the user or by an external link.
All you need to run this sub is to place the code in the sheet module for the relevant sheet and change B12 cell.
A Worksheet Change: Change Range Values on Cell Change
Worksheet_ in the signature Private Sub Worksheet_Change(ByVal Target As Range) indicates that this procedure belongs in the sheet module, e.g. Sheet1, of the worksheet where you want it applied (not in the ThisWorkbook module nor in a standard module, e.g. Module1). Such a procedure will run automatically (get triggered) when an event occurs, particularly for this procedure, after a manual change has happened in a range i.e. after
you write something into the formula bar and press enter,
you (copy) paste values to a range, or
you use VBA to write values to a range.
In this procedure, if you want to write something to a range of the worksheet, to not retrigger the event and possibly end up with an endless loop ('crashing' Excel), you will disable events before you start writing, and enable them after writing as you did in your code. If an error occurs between these two lines, the events will stay disabled and the code won't trigger until they are enabled again.
To check if events are enabled you could use the line Debug.Print Application.EnableEvents in another procedure or in the Immediate window just use ?Application.EnableEvents and press enter. Similarly, if the answer is False, in the Immediate window, you can use Application.EnableEvents = True and press enter to enable events.
The line Set rOld = Range("A1:E1").Value is wrong and results in
Run-time error '424': Object required
To avoid the error you could use one of the following:
Dim rgOld As Range: Set rgOld = Range("A1:E1")
Range("A15:E15").Value = rgOld.Value
Target.Value = sNewValue
Dim OldValues() As Variant: OldValues = Range("A1:E1").Value
Range("A15:E15").Value = OldValues ' or after the following line
Target.Value = sNewValue
Range("A15:E15").Value = Range("A1:E1").Value
Target.Value = sNewValue
Basically, you want to write the data before rewriting the new value. Optionally, in the second case where the data is written to an array (OldValues), you can write the values afterward.
Since the use of an additional variable is kind of redundant in the first two cases, the last (the simplest, the most straightforward) case is used in the following code.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address <> "$B$12" Then Exit Sub
Dim NewString As String: NewString = CStr(Target.Value)
Application.EnableEvents = False
Application.Undo ' this will also write (trigger the event)
Me.Range("A15:E15").Value = Me.Range("A1:E1").Value
Target.Value = NewString ' redo
Application.EnableEvents = True
End Sub
If you want to modify (experiment with) the code, you should introduce some error handling so you don't end up with events disabled.
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo ClearError
If Target.Address <> "$B$12" Then Exit Sub
Dim NewString As String: NewString = CStr(Target.Value)
Application.EnableEvents = False
Application.Undo ' this will also write (trigger the event)
Me.Range("A15:E15").Value = Me.Range("A1:E1").Value
Target.Value = NewString ' redo
SafeExit:
On Error Resume Next
If Not Application.EnableEvents Then Application.EnableEvents = True
On Error GoTo 0
Exit Sub
ClearError:
Debug.Print "Run-time error'" & Err.Number & "': " & Err.Description
Resume SafeExit
End Sub
One thing is basic: how did you create this function? Did you open the Excel VBA editor, select a sheet and chose the corresponding event, like I did in the following screenshot:
As you see, the macro is linked to "Sheet1", it is linked to the events of the "Worksheet" itself, and it is triggered by any "Change" of that worksheet.

Error Message when changing value of particular cell and restore previous value VBA

I am trying to create a code using vba whereby I want to make a certain cell B2 read-only and unchangeable when session is unlocked (I have a lock and unlock module for later whereby locked disallow editing and unlocked allows editing).
The code aims to give an error message and restore the cell to the previous value before edits are made when session is locked.
Problem: However, currently the results from this code successfully gave an error message when edit is done when locked BUT made the cell blank after the error message when I actually want it to restore to the previous value before edit was made
Please help if you know what went wrong and thank you in advance
Public locked As Boolean
Dim oldValue As Variant
Private Sub worksheet_SelectionChange(ByVal Target As Range)
oldValue = Target.Value
End Sub
Private Sub worksheet_Change(ByVal Target As Range)
If Target.Row = 2 And Target.Column = 2 Then
If locked Then
If Target.Value <> oldValue Then
Target.Value = oldValue
MsgBox "You are not allowed to edit!"
End If
End If
End If
End Sub
An Events Duo: Change and SelectionChange
In the Worksheet_SelectionChange event you can safely use Target because you can select only one cell at a time.
In the Worksheet_Change event you could have copied hundreds of cells which are the cells Target is referring to. But you are only interested in one cell, so use intersect and use a variable to get this single cell and do the operations necessary on it. Also, to avoid an endless loop by constantly retriggering the event, disable events before writing to the worksheet but don't forget to enable them immediately after writing.
Option Explicit
' If you're using the variables outside of this module, they need
' to be declared as 'Public'. Otherwise, use 'Private' ('Dim' is the same
' but it's kind of reserved for inside procedures).
Public Locked As Boolean
Private Const CellAddress As String = "B2"
Private OldValue As Variant
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Range(CellAddress), Target) Is Nothing Then
OldValue = Target.Value
End If
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim iCell As Range: Set iCell = Intersect(Range(CellAddress), Target)
If Not iCell Is Nothing Then
If Locked Then
If StrComp(CStr(iCell.Value), CStr(OldValue), vbTextCompare) _
<> 0 Then
Application.EnableEvents = False ' prevent retriggering
iCell.Value = OldValue
Application.EnableEvents = True
MsgBox "You are not allowed to edit!"
End If
End If
End If
End Sub

Copy paste values triggered by worksheet change event is not working

I am using worksheet change event to trigger copy paste values. Worksheet change code is in the sheet2
Sub worksheet_change(ByVal Target As Range)
Application.EnableEvents = True
Set Target = Range("AB2")
If Target.Value = "OK" Then
Call myTR1
End If
Please note AB2 cell takes it's value from another sheet
Copy paste code is in a Module
Sub myTR1()
Sheets("BA1").Range("AR6:AS8").Value = Sheets("BA1").Range("AL17:AM19").Value
End Sub
When target range changes to "OK", my copy paste macro is not triggering. What am I doing wrong?
Using your eaxct code worked, although you didnt have end sub in your example?
EDIT:
Bear in mind the 'OK' is case sensitive so it will have to be in uppercase to fire, if you want it to fire either on lower or upper you can use the second code.
Sub worksheet_change(ByVal Target As Range)
Application.EnableEvents = True
Set Target = Range("AB2")
If Target.Value = "OK" Then
Call myTR1
End If
End Sub
Sub worksheet_change(ByVal Target As Range)
Application.EnableEvents = True
Set Target = Range("AB2")
If Target.Value = "OK" Or Target.Value = "ok" Then
Call myTR1
End If
End Sub

MS Excel Objects Lock Row based on Value working with Other Object

I have programming, with major help from others, that works great for two separate workbooks. The problem is that I can't seem to have them both work within the same workbook and I don't know why.
We have a large contact database (4800 rows) workbook with a lot of sorting macros. I use the following to allow the user to double-click a cell to select or de-select a contact. This is under the Excel Objects, Sheet1 (MASTER):
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'Limit Target count to 1
If Target.Count > 1 Then Exit Sub
'Isolate Target to a specific range
If Intersect(Target, Range("SelectionMaster")) Is Nothing Then Exit Sub
'set Target font tp "marlett"
Target.Font.Name = "marlett"
'Check value of target
If Target.Value < "a" Then
Target.Value = "a" 'Sets target Value = "a"
Cancel = True
Exit Sub
End If
If Target.Value = "a" Then
Target.Value = "r"
Cancel = True
Exit Sub
End If
If Target.Value = "r" Then
Target.ClearContents 'Sets Target Value = ""
Cancel = True
Exit Sub
End If
End Sub
In another workbook, I tested the following for locking a particular row if an 'X' is placed in Column AZ (end of contact data). This is under the Excel Objects, Sheet1 (Sheet1):
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim LR As Long
If Not Target.Column = 52 Then Exit Sub
If Target.Count > 1 Then Exit Sub
If UCase(Target.Value) = "X" Then
ActiveSheet.Unprotect
Target.EntireRow.Locked = True
ActiveSheet.Protect
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Locked Then
If MsgBox("Row is locked. Do you want to change the value ?", vbYesNo) = vbYes Then
ActiveSheet.Unprotect
Target.EntireRow.Locked = False
Cells(ActiveCell.Row, 52).Value = ""
ActiveSheet.Protect
End If
End If
End Sub
In the Database file, I have certain rows that identify the contact's category that I would like to have locked. All other cells can be changed. If I copy over the 2nd code to the database file, it doesn't work correctly. Instead it locks all of the cells and prompts the message box regardless of an 'X' in Column AZ. Can these two not co-exist or what is this newb doing wrong?

Excel macro code for clearing formulas in cells does not work when the sheet is protected

After some googling I finally found some code where I could prevent users from placing formulas inside cells. It works great, that's until I protected the sheet. Can anyone tell me what I'm doing wrong? I'm really new to VB.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Application.EnableEvents = False
On Error Resume Next
Range("I39").SpecialCells(xlCellTypeFormulas).ClearContents
On Error GoTo 0
Application.EnableEvents = True
End If
End Sub
The entire code for my sub is as follows. I need to stop users from pasting in the cells and putting formulas in them.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, Range("C26")) Is Nothing Then
Application.CutCopyMode = True
Application.EnableEvents = False
On Error Resume Next
Range("C26").SpecialCells(xlCellTypeFormulas).ClearContents
On Error GoTo 0
Application.EnableEvents = True
End If
End Sub
Here is a version that facilitates formula checking over a range of cells:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rNoFormulas As Range
Set rNoFormulas = Range("C26:I26")
If Intersect(Target, rNoFormulas) Is Nothing Then Exit Sub
If Target.HasFormula Then
Application.EnableEvents = False
Target.ClearContents
MsgBox "formulas not allowed in cell " & Target.Address
Target.Select
Application.EnableEvents = True
End If
End Sub
If you want to allow data entry in cell C26, but not formula entry, then use the Change Event:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rNoFormulas As Range
Set rNoFormulas = Range("C26")
If Intersect(Target, rNoFormulas) Is Nothing Then Exit Sub
If rNoFormulas.HasFormula Then
Application.EnableEvents = False
rNoFormulas.ClearContents
MsgBox "formulas not allowed in cell C26"
rNoFormulas.Select
Application.EnableEvents = True
End If
End Sub
If you just want to protect certain cells only, no vba code is need.
follow this step :
Open sheet that contains cells or columns that you want to protect, press ctrl while selecting those cells or column to be protect, then right click, choose format cells, choose protection tab and uncheck the locked option. those cells or column will not be locked although you have protected the sheet. default setting is all cells in the sheets is locked so you must choose which cells you want to unlock while protecting the sheet. you may record a macro if you still want to use vba. hope this help

Resources