I have a strange issue, I have a sheet in excel 2013 which uses the doubleclick to select a cell( which has some text in it that I want locked so the user does not change), change the text colour to highlight the chosen cell and then put a value based on the target.column in a cell further along the row.
It works fine if I unlock the sheet but all attempts to lock the sheet end up with a error in the value of "Target.row" I put the msg statement in and I can see that at the end of each call the active cell then moves to the next unlocked cell and wont then move/update the values when you next click on a wanted cell to highlight.
I have tried all sorts of fixes for this and made many code changes. Currently the code is:
Private Sub Workbook_Open()
' protect worksheets but allow macros
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
ws.Protect Password:="Purple15", userinterfaceonly:=True
Next ws
End Sub
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'Sheet3.Protect Password:="Purple15", UserInterFaceOnly:=True
Dim i As Integer
Dim d As Integer
MsgBox " row is " & Target.Row & " col is " & Target.Column
'Cells(Target.Row, 1).Value = "S"
For d = 1 To 1000
Next d
' above just slows it down to see effect
Sheet3.Unprotect Password:="Purple15"
'Cells(Target.Row, 1).Value = "U"
' check if double click is in the range cols 9 to 13 as these are the only ones they should choose
' if so then set font colour to red for the chosen cell and put chosen col number in col 16 for the sheet to then pick up from
'Cells(5, 1).Value = "U"
If Target.Column >= 9 And Target.Column <= 13 Then
'Cells(Target.Row, 1).Value = 2
Cells(Target.Row, 9).Font.Color = vbBlack
Cells(Target.Row, 10).Font.Color = vbBlack
Cells(Target.Row, 11).Font.Color = vbBlack
Cells(Target.Row, 12).Font.Color = vbBlack
Cells(Target.Row, 13).Font.Color = vbBlack
Target.Font.Color = vbRed
Cells(Target.Row, 16) = (Target.Column)
' also check if the double click is in the reset box, if so then reset all the values in col 16 to the starting condition of 9
ElseIf Target.Column = 2 And Target.Row = 3 Then
'Cells(3, 1).Value = 3
For i = 8 To 300
Cells(i, 1).Value = " "
Cells(i, 9).Font.Color = vbBlack
Cells(i, 10).Font.Color = vbBlack
Cells(i, 11).Font.Color = vbBlack
Cells(i, 12).Font.Color = vbBlack
Cells(i, 13).Font.Color = vbBlack
If Cells(i, 16).Value >= 10 Then Cells(i, 16).Value = 9
Next i
Else
End If
'Cells(5, 1).Value = " "
'Cancel = True
Sheet3.Protect Password:="Purple15", userinterfaceonly:=True
'Cells(5, 1).Value = "L"
End Sub
You may want to look into using buttons. That way you don't have to worry about end-users changing values (as easily). I created a spreadsheet with only one row and "SomeText 1" in column A, "SomeText 2" in column B and "SomeText 3" in column C. Below is the code and I think it is working as you expect.
In "ThisWorkbook" I used your exact code:
Private Sub Workbook_Open()
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
ws.Protect Password:="Purple15", userinterfaceonly:=True
Next ws
End Sub
In "Sheet1" I used this:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Target.Column >= 1 And Target.Column <= 3 Then
'Reset all of the "Buttons" to black
Cells(Target.Row, 1).Font.Color = vbBlack
Cells(Target.Row, 2).Font.Color = vbBlack
Cells(Target.Row, 3).Font.Color = vbBlack
'Makes the one they clicked red
Target.Font.Color = vbRed
'Change focus so you don't get the "Protected Worksheet"
' warning after a double-click
Cells(Target.Row, 6).Select
'Unlock the cell you're editing
Cells(Target.Row, 6).Locked = False
'Set the cell's value
Cells(Target.Row, 6) = (Target.Column)
'Lock it again
Cells(Target.Row, 6).Locked = True
End If
End Sub
Is that what you are looking for?
Related
I'm trying to get a macro to operate by calling out another macro to unlock a worksheet to allow a RFID reader to scan and input data and then protect the document again to allow it from being edited.
Private Sub Worksheet_Change(ByVal Target As Range)
' call another macro
Call UnProtect
' End Sub
' Dim i As Integer
' MsgBox (Target.Row & ":" & Target.Column)
' For i = 8 To 200
If Target.Column = 3 And Target.Row <= 12 Then
If Cells(Target.Row, Target.Column).Value <> "" And Cells(Target.Row, "E").Value = "" Then
' Cells(Target.Row, "E").Value = Now()
' Cells(Target.Row, "E").NumberFormat = "h:mm AM/PM"
End If
End If
' Next
' Range("E:E").EntireColumn.AutoFit
' End Sub
' Private Sub Worksheet_Change(ByVal Target As Range)
' Dim i As Integer
' MsgBox (Target.Row & ":" & Target.Column)
' For i = 8 To 200
If Target.Column = 1 And Target.Row <= 17 Then
If Cells(Target.Row, Target.Column).Value <> "" And Cells(Target.Row, "B").Value = "" Then
Cells(Target.Row, "B").Value = Now()
' Cells(Target.Row, "F").NumberFormat = "h:mm AM/PM"
End If
End If
' Next
' Range("F:F").EntireColumn.AutoFit
' End Sub
' Private Sub Worksheet_Change(ByVal Target As Range)
' Dim i As Integer
' MsgBox (Target.Row & ":" & Target.Column)
' For i = 8 To 200
If Target.Column = 3 And Target.Row >= 15 Then
If Cells(Target.Row, Target.Column).Value <> "" And Cells(Target.Row, "D").Value = "" Then
Cells(Target.Row, "D").Value = Now()
Cells(Target.Row, "D").NumberFormat = "mm/dd/yyy"
End If
End If
' Next
Range("D:D").EntireColumn.AutoFit
' End Sub
' call another macro
Call Protect
End Sub
The two macros it is calling to are
Sub UnProtect()
'Unprotect a worksheet
Sheets("Sign in Sheet").UnProtect
End Sub
and
Sub Protect()
'Protect a worksheet
Sheets("Sign in Sheet").Protect
End Sub
However, when I only include the unlock macro, the code will work fine. But when I add the protect macro, an error code will come up
Run-Time Error '1004':
Unable to set the NumberFormat property of the Range class
and it points to
Cells(Target.Row, "D").NumberFormat = "mm/dd/yyyy"
Any ideas as to what exactly is happening.
I see no provision for a case when Target is more than a single cell and there's a pretty good chance that the Worksheet_Change is trying to run on top of itself.
Cycle through each range object in Target and disable event triggers.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo safe_exit
Application.EnableEvents = False
Call Unprotect
Dim t As Range
If Not Intersect(Target, Range("A1:A17")) Is Nothing Then
For Each t In Intersect(Target, Range("A1:A17"))
If t.Value <> vbNullString And t.Offset(0, 1).Value <> vbNullString Then
t.Offset(0, 1) = Now
t.Offset(0, 1).NumberFormat = "h:mm AM/PM"
End If
Next t
End If
If Not Intersect(Target, Range("C1:C12")) Is Nothing Then
For Each t In Intersect(Target, Range("C1:C12"))
If t.Value <> vbNullString And t.Offset(0, 2).Value <> vbNullString Then
t.Offset(0, 2) = Now
t.Offset(0, 2).NumberFormat = "h:mm AM/PM"
End If
Next t
'I don't understand why column F comes into play here
' Range("F:F").EntireColumn.AutoFit
End If
If Not Intersect(Target, Range("C15:C999999")) Is Nothing Then
For Each t In Intersect(Target, Range("C15:C999999"))
If t.Value <> vbNullString And t.Offset(0, 1).Value <> vbNullString Then
t.Offset(0, 1) = Now
t.Offset(0, 1).NumberFormat = "mm/dd/yyy"
End If
Next t
Range("D:D").EntireColumn.AutoFit
End If
Call Protect
safe_exit:
Application.EnableEvents = True
End Sub
I'm currently using Excel 2010 and am trying to run some code I put together in VBA for Applications (after hitting alt+F11). I typed up the code in a notepad that appeared after double clicking the project I wanted to work on. I also saved everything as Excel Macro Enabled Workbook (*.xlsm).
I am trying to color the backgrounds of Column D either green or red if columns S, T, and U meet the criteria. If the columns all have a value of 0 then Cell D should be colored green. If not, it should be colored red.
Sub GreenOrRed()
Dim i As Integer
For i = 2 To i = 27293
If (Cells(i, "S").Value = 0 And Cells(i, "T").Value = 0 And Cells(i, "U").Value = 0) Then
Cells(i, "D").Interior.ColorIndex = 10
Else
Cells(i, "D").Interior.ColorIndex = 9
End If
Next i
End Sub
The code runs and doesn't throw any error but it also doesn't do anything. What am I doing wrong?
You are using counter in For loop incorrectly. It should be like this...
For i = 2 To 27293
Changed For condition.
Try this:-
Sub GreenOrRed()
Dim i As Integer
For i = 2 To 27293
If (Cells(i, "S").Value = 0 And Cells(i, "T").Value = 0 And Cells(i, "U").Value = 0) Then
Cells(i, "D").Interior.ColorIndex = 10
Else
Cells(i, "D").Interior.ColorIndex = 9
End If
Next i
End Sub
A slightly different approach:
Sub GreenOrRed()
Dim r As Range, rr As Range
Set rr = Range("D1:D27293")
For Each r In rr
If r.Offset(0, 15).Value = 0 And r.Offset(0, 16).Value = 0 And r.Offset(0, 17).Value = 0 Then
r.Interior.ColorIndex = 10
Else
r.Interior.ColorIndex = 9
End If
Next r
End Sub
You might consider setting one (or two) conditional formatting rules.
Option Explicit
Sub GreenOrRed()
With ActiveSheet
With .Range(.Cells(2, "D"), .Cells(.Rows.Count, "D").End(xlUp))
.Interior.ColorIndex = 9
.FormatConditions.Delete
With .FormatConditions.Add(Type:=xlExpression, Formula1:="=and(sum($S2)=0, sum($T2)=0, sum($U2)=0)")
.Interior.ColorIndex = 10
.StopIfTrue = True
End With
End With
End With
End Sub
I've used individual SUM functions to ensure that any text returns a numerical value of zero.
Alternate AutoFilter method.
Sub GreenOrRedFiltered()
With ActiveSheet
If .AutoFilterMode Then .AutoFilterMode = False
With .Range(.Cells(1, "D"), .Cells(.Rows.Count, "D").End(xlUp)).Resize(, 18)
.Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0).Columns(1).Interior.ColorIndex = 9
.AutoFilter Field:=16, Criteria1:=0, Operator:=xlOr, Criteria2:=vbNullString
.AutoFilter Field:=17, Criteria1:=0, Operator:=xlOr, Criteria2:=vbNullString
.AutoFilter Field:=18, Criteria1:=0, Operator:=xlOr, Criteria2:=vbNullString
With .Resize(.Rows.Count - 1, .Columns.Count).Offset(1, 0)
If CBool(Application.Subtotal(103, .Cells)) Then
.Columns(1).SpecialCells(xlCellTypeVisible).Interior.ColorIndex = 10
End If
End With
End With
If .AutoFilterMode Then .AutoFilterMode = False
End With
End Sub
Is there a way I can automate the date or time once the I enter the data from the User_Form via "enter/click" button? I've tried this code but it keeps restarting my excel workbook. On top of that, I have a ton of other codes in the Private Sub Worksheet_Change(ByVal Target As Range)
Is it possible it's overloaded ?
So I'm thinking if I could code it with my Userform_click() I'd be better off?
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i As Integer
For i = 16 To 100
If Cells(i, 3).Value <> "" Then
Cells(i, 1).Value = Date & " "
Cells(i, 1).NumberFormat = "mm/dd/yy"
End If
Next
End Sub
You need to add Application.EnableEvents = False in the beginning of your Sub, otherwise it will keep running it every time a value is changed inside the worksheet (like when you change it inside your For i = 16 To 100 loop).
Code
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i As Integer
Application.EnableEvents = False
For i = 16 To 100
If Cells(i, 3).Value <> "" Then
Cells(i, 1).Value = Date & " "
Cells(i, 1).NumberFormat = "mm/dd/yy"
End If
Next i
Application.EnableEvents = True '<-- restore to original setting
End Sub
Edit 1: You can write your Sub in another way, that it will enter it only if a cell is changed inside the searched Range("C16:C100"). Only if the modified cell is inside that range, then check each cell if the Value <> "".
Private Sub Worksheet_Change(ByVal Target As Range)
Dim C As Range
Application.EnableEvents = False
If Not Intersect(Range("C16:C100"), Target) Is Nothing Then
For Each C In Intersect(Range("C16:C100"), Target)
If C.Value <> "" Then
C.Offset(, -2).Value = Date & " "
C.Offset(, -2).NumberFormat = "mm/dd/yy"
End If
Next C
End If
Application.EnableEvents = True
End Sub
I have the following code to insert a new row based on the cell value. How can I modify this to also copy the value in column A for example) to the newly inserted row?
Private Sub Worksheet_Change(ByVal Target As Range)
Set Rng = Range("B11:B50")
If Target.Count = 1 Then
If Target.Value = "Annual" Then
If Not Intersect(Target, Rng) Is Nothing Then
Application.EnableEvents = False
Target(1).Offset(1, 0).EntireRow.Insert Shift:=xlDown
Application.EnableEvents = True
End If
End If
End If
End Sub
Cells(Target.Row + 1, 1).Value = Cells(Target.Row, 1).Value
To copy both A & B
Cells(Target.Row + 1, 1).Value = Cells(Target.Row, 1).Value
Cells(Target.Row + 1, 2).Value = Cells(Target.Row, 2).Value
Could someone please help me work out how to copy and rename sheets based on values on another sheet,
currently the sheet is being called "CLO (2)" not "CLO 1.2". I want the code to copy the sheet named "CLO" and rename it based on values found on the sheet called "TMP Data", using the cell values from B7 and C7 and below (B and C values create the sheet name).
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count > 1 Then Exit Sub
If Target.Address = "$B$6" Then
Application.EnableEvents = False
With Target.Offset(1, 0)
Range(.Cells(1), .Cells(1).End(xlDown)).ClearContents
.Value = 1
.Resize(Target.Value, 1).DataSeries _
Rowcol:=xlColumns, Type:=xlLinear, Step:=1
End With
Target.Offset(0, 1).Activate
ElseIf Not Intersect(Target, Columns("C")) Is Nothing Then
If Target.Row > 6 And Application.Count(Target.Offset(0, -1).Resize(1, 2)) = 2 Then
On Error GoTo Fìn
Application.EnableEvents = False
Dim w As Long
For w = 1 To Target.Value
Sheets("CLO").Copy(after:=Sheets(Sheets.Count)).Name = _
Target.Offset(0, -1) & Chr(46) & w
Next w
Me.Activate
End If
End If
Fìn:
Application.EnableEvents = True
End Sub
Here is the Excel file
By default the sheet will be copied as CLO (2), rename it after it has been copied:
Sheets("CLO").Copy After:=Sheets(Sheets.Count)
Sheets(Sheets.Count).Name = Target.Offset(0, -1).Value & Chr(46) & w