VBA for Formatting

accountant123

New Member
Joined
Jun 11, 2019
Messages
2
Would anyone be able to help me create a macro for a sheet I'm working on please?

I have a list of data (~1000 lines), for each row, I would like a check box in col. A of each row, which when ticked, locks the 66 cells to the right (to col. BO) to prevent any editing and ideally highlights the column as yellow.
When the check box is then unticked, I would like the same cells to unlock to allow editing.

A further development on this if possible, would be for when the box is unticked and an edit is made, a change log to be created in a separate sheet with what it has changed to?
 

Excel Facts

Remove leading & trailing spaces
Save as CSV to remove all leading and trailing spaces. It is faster than using TRIM().
Assuming you have a worksheet of codename Sheet2 for the logging, here is an option.
Note, instead of creating 1000 check-boxes, I've just used a double click event on the range. A10 down 1000 rows.
Please modify to suit & add some error handling & tweaks as required.
Locking worksheets can create complications for users, navigation, filtering, printing, whatever & you can tie yourself in knots trying to cover everything you need.
Anyway, this will give you some ideas & I'll leave it to you to change/develop further.

Code:
'The next few lines define the range of cells that show "LOCKED" or "UNLOCKED" and control what is blocked
Const mlFIRST_DATA_COL As Long = 1 '1 means column "A"
Const mlFIRST_DATA_ROW As Long = 10 '10 means the first data row is row 10
Const mlHOW_MANY_DATA_ROWS As Long = 1000 '1000 means there are 1000 rows of data
Const mlHOW_MANY_COLUMNS_ARE_LOCKED As Long = 66 '66 is for the 66 columns on the immediate RHS of "FIRST_DATA_COL"


Private Sub Worksheet_Activate()


    Me.Cells(mlFIRST_DATA_ROW, mlFIRST_DATA_COL).Resize(mlHOW_MANY_DATA_ROWS).Name = "rngSwitchCells"
    Me.Cells(mlFIRST_DATA_ROW, mlFIRST_DATA_COL).Resize(mlHOW_MANY_DATA_ROWS).Offset(, 1).Resize(, mlHOW_MANY_COLUMNS_ARE_LOCKED).Name = "rngLogChanges"


End Sub


Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)


    Const sWORD_LOCKED As String = "LOCKED"
    Const sWORD_UNLOCKED As String = "UNLOCKED"
    Const sPASSWORD As String = "accountant123"


    'if the cell double clicked is one of the cells that controls the switching between LOCKED & UNLOCKED
    If Not Intersect(Target, Me.Range("rngSwitchCells")) Is Nothing Then
    
        Cancel = True
        'rngSwitchCells.Locked = False
        Me.Protect Password:=sPASSWORD, UserInterfaceOnly:=True
        
        'if cell already says LOCKED
        If Target.Value2 = sWORD_LOCKED Then
            'Data is currently locked. change to unlocked
            Target.Value2 = sWORD_UNLOCKED
            Target.Interior.Color = xlNone
            Target.Offset(, 1).Resize(mlHOW_MANY_COLUMNS_ARE_LOCKED).Locked = False
            
        Else
            'Data was not locked, change it to locked
            Target.Value2 = sWORD_LOCKED
            Target.Interior.Color = vbYellow
            Target.Offset(, 1).Resize(mlHOW_MANY_COLUMNS_ARE_LOCKED).Locked = True
        End If
        
    End If
    
End Sub




Private Sub Worksheet_Change(ByVal Target As Range)


    Dim lNextRow As Long
    Dim rngOneCell As Excel.Range
    
    If Not Intersect(Target, Me.Range("rngLogChanges")) Is Nothing Then
        For Each rngOneCell In Target.Cells
            With Sheet2
                lNextRow = .Cells(Sheet2.Rows.Count, 1).End(xlUp).Row + 1
                With .Cells(lNextRow, 1)
                    .Value = Now
                    .Offset(, 1).Value2 = rngOneCell.Address
                    .Offset(, 2).Value2 = rngOneCell.Value2
                End With
            End With
        Next rngOneCell
    End If


End Sub
 
Upvote 0
Many thanks! I'm getting a run time error 'Method 'Range' of object_Worksheet' failed. Sorry - I'm a real amateur on VBA!

Assuming you have a worksheet of codename Sheet2 for the logging, here is an option.
Note, instead of creating 1000 check-boxes, I've just used a double click event on the range. A10 down 1000 rows.
Please modify to suit & add some error handling & tweaks as required.
Locking worksheets can create complications for users, navigation, filtering, printing, whatever & you can tie yourself in knots trying to cover everything you need.
Anyway, this will give you some ideas & I'll leave it to you to change/develop further.

Rich (BB code):
'The next few lines define the range of cells that show "LOCKED" or "UNLOCKED" and control what is blocked
Const mlFIRST_DATA_COL As Long = 1 '1 means column "A"
Const mlFIRST_DATA_ROW As Long = 10 '10 means the first data row is row 10
Const mlHOW_MANY_DATA_ROWS As Long = 1000 '1000 means there are 1000 rows of data
Const mlHOW_MANY_COLUMNS_ARE_LOCKED As Long = 66 '66 is for the 66 columns on the immediate RHS of "FIRST_DATA_COL"


Private Sub Worksheet_Activate()


    Me.Cells(mlFIRST_DATA_ROW, mlFIRST_DATA_COL).Resize(mlHOW_MANY_DATA_ROWS).Name = "rngSwitchCells"
    Me.Cells(mlFIRST_DATA_ROW, mlFIRST_DATA_COL).Resize(mlHOW_MANY_DATA_ROWS).Offset(, 1).Resize(, mlHOW_MANY_COLUMNS_ARE_LOCKED).Name = "rngLogChanges"


End Sub


Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)


    Const sWORD_LOCKED As String = "LOCKED"
    Const sWORD_UNLOCKED As String = "UNLOCKED"
    Const sPASSWORD As String = "accountant123"


    'if the cell double clicked is one of the cells that controls the switching between LOCKED & UNLOCKED
    If Not Intersect(Target, Me.Range("rngSwitchCells")) Is Nothing Then
    
        Cancel = True
        'rngSwitchCells.Locked = False
        Me.Protect Password:=sPASSWORD, UserInterfaceOnly:=True
        
        'if cell already says LOCKED
        If Target.Value2 = sWORD_LOCKED Then
            'Data is currently locked. change to unlocked
            Target.Value2 = sWORD_UNLOCKED
            Target.Interior.Color = xlNone
            Target.Offset(, 1).Resize(mlHOW_MANY_COLUMNS_ARE_LOCKED).Locked = False
            
        Else
            'Data was not locked, change it to locked
            Target.Value2 = sWORD_LOCKED
            Target.Interior.Color = vbYellow
            Target.Offset(, 1).Resize(mlHOW_MANY_COLUMNS_ARE_LOCKED).Locked = True
        End If
        
    End If
    
End Sub




Private Sub Worksheet_Change(ByVal Target As Range)


    Dim lNextRow As Long
    Dim rngOneCell As Excel.Range
    
    If Not Intersect(Target, Me.Range("rngLogChanges")) Is Nothing Then
        For Each rngOneCell In Target.Cells
            With Sheet2
                lNextRow = .Cells(Sheet2.Rows.Count, 1).End(xlUp).Row + 1
                With .Cells(lNextRow, 1)
                    .Value = Now
                    .Offset(, 1).Value2 = rngOneCell.Address
                    .Offset(, 2).Value2 = rngOneCell.Value2
                End With
            End With
        Next rngOneCell
    End If


End Sub
 
Upvote 0
Taking my cue from Fazza's post, I too have decided to use double clicking to lock and unlock the cells (rather than adding 1000 or so CheckBoxes). A locked row (Columns A:BO) will be indicated by a yellow highlight, non-locked rows will not be highlighted. Also, the logging of any changes made to non-locked cells is placed on a worksheet named "Sheet2" (change the red highlighted text to the actual name of your log sheet if different from "Sheet2").

The following is Event Code for the sheet the user will enter data into (see install instructions below)...
Code:
[table="width: 500"]
[tr]
	[td]Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  Cancel = True
  If Target.Interior.ColorIndex = 6 Then
    Intersect(Target.EntireRow, Columns("A:BO")).Interior.ColorIndex = xlColorIndexNone
  Else
    Intersect(Target.EntireRow, Columns("A:BO")).Interior.ColorIndex = 6
  End If
End Sub

Private Sub Worksheet_Change(ByVal Target As Range)
  Dim Cell As Range
  Application.EnableEvents = False
  If Sheets("[B][COLOR="#FF0000"]Sheet2[/COLOR][/B]").Range("A1").Value = "" Then Sheets("[B][COLOR="#FF0000"]Sheet2[/COLOR][/B]").Range("A1:C1") = Array("Date", "Cell Address", "Value")
  For Each Cell In Target
    If Cell.Interior.ColorIndex = 6 Or IsNull(Intersect(Cell.EntireRow, Columns("A:BO")).Interior.ColorIndex) Then
      MsgBox "You have attempted to modify a locked cell; your action will now be cancelled."
      Application.Undo
      GoTo Undone
    End If
  Next
  For Each Cell In Target
    If Cell.Column < 67 Then
      With Sheets("[B][COLOR="#FF0000"]Sheet2[/COLOR][/B]").Cells(Rows.Count, "A").End(xlUp).Offset(1)
        .Value = Now
        .Offset(, 1).Value = Cell.Address(0, 0)
        .Offset(, 2).Value = Cell.Value
      End With
    End If
  Next
  Sheets("[B][COLOR="#FF0000"]Sheet2[/COLOR][/B]").Columns("A:C").AutoFit
Undone:
  Application.EnableEvents = True
End Sub[/td]
[/tr]
[/table]

HOW TO INSTALL Event Code
------------------------------------
If you are new to event code procedures, they are easy to install. To install it, right-click the name tab at the bottom of the worksheet that is to have the functionality to be provided by the event code and select "View Code" from the popup menu that appears. This will open up the code window for that worksheet. Copy/Paste the event code into that code window. That's it... the code will now operate automatically when its particular event procedure is raised by an action you take on the worksheet itself. Note... if you are using XL2007 or above, make sure you save your file as an "Excel Macro-Enabled Workbook (*.xlsm) and answer the "do you want to enable macros" question as "yes" or "OK" (depending on the button label for your version of Excel) the next time you open your workbook.
 
Last edited:
Upvote 0
To overcome that error, please close Excel & start again.
I think it is just a once-off setup/initialisation issue (creating a named range on worksheet activation, and it hasn't been done the very first time) & won't re-occur.
 
Upvote 0

Forum statistics

Threads
1,221,310
Messages
6,159,176
Members
451,543
Latest member
cesymcox

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top