Correcting one code causes another to stop working - excel

I am working on a document in which clickable cells place different values in column M on sheets 1 and 3. On sheet 1 when column M reads COMPLETE it will be cut from sheet 1 and pasted in sheet 2 when column M reads PARTIAL HOLD it will be cut from sheet 1 and pasted into sheet 3. I am having many problems with this but the problem I am asking for help on here is that in the following code the moves will work but i get a "run-time error '424' Object Required" and is not accepting Time as an object in my line of code Target.Offset(, 4).Value = Time but when I fix the issue in the code for the clickable cells the rows will no longer cut and paste.
This first code is the code that allows the rows to move but gets me an error
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngDest As Range, rngDest2 As Range, rngDest3 As Range
If UCase(Target.Value) = "PARTIAL HOLD" Then
Set rngDest = Sheet3.Range("A5:Q5")
If Not Intersect(Target, Sheet1.Range("M5:M290")) Is Nothing Then
Application.EnableEvents = False
Target.EntireRow.Cut
rngDest.Insert Shift:=xlDown
Target.EntireRow.Delete
Application.EnableEvents = True
End If
ElseIf UCase(Target.Value) = "PROGRESSING" Then
Set rngDest3 = Sheet1.Range("A5:Q5")
If Not Intersect(Sheet3.Cells(Target.Row, Target.Column), Sheet3.Range("M5:M290")) Is Nothing Then
Application.EnableEvents = False
Target.EntireRow.Cut
rngDest3.Insert Shift:=xlDown
Target.EntireRow.Delete
Application.EnableEvents = True
End If
ElseIf UCase(Target.Value) = "COMPLETE" Then
Set rngDest2 = Sheet2.Range("A5:Q5")
If Not Intersect(Target, Sheet1.Range("M5:M290")) Is Nothing Then
Application.EnableEvents = False
Target.EntireRow.Cut
rngDest2.Insert Shift:=xlDown
Target.EntireRow.Delete
Application.EnableEvents = True
End If
End If
End Sub
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Target.Column = 11 Then
Cancel = True
Target.Offset(, 2).Value = "IN PROGRESS"
Target.Offset(, 4).Value = Time
ElseIf Target.Column = 12 Then
Cancel = True
Target.Offset(, 1).Value = "COMPLETE"
Target.Offset(, 4).Value = Time
ElseIf Target.Column = 14 Then
Cancel = True
Target.Offset(, -1).Value = "PARTIAL HOLD"
End If
End Sub
The next code is the correction I have made to the clickable cells, but this stops the rows from cutting and pasting
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rngDest As Range, rngDest2 As Range, rngDest3 As Range
If UCase(Target.Value) = "PARTIAL HOLD" Then
Set rngDest = Sheet3.Range("A5:Q5")
If Not Intersect(Target, Sheet1.Range("M5:M290")) Is Nothing Then
Application.EnableEvents = False
Target.EntireRow.Cut
rngDest.Insert Shift:=xlDown
Target.EntireRow.Delete
Application.EnableEvents = True
End If
ElseIf UCase(Target.Value) = "PROGRESSING" Then
Set rngDest3 = Sheet1.Range("A5:Q5")
If Not Intersect(Sheet3.Cells(Target.Row, Target.Column),
Sheet3.Range("M5:M290")) Is Nothing Then
Application.EnableEvents = False
Target.EntireRow.Cut
rngDest3.Insert Shift:=xlDown
Target.EntireRow.Delete
Application.EnableEvents = True
End If
ElseIf UCase(Target.Value) = "COMPLETE" Then
Set rngDest2 = Sheet2.Range("A5:Q5")
If Not Intersect(Target, Sheet1.Range("M5:M290")) Is Nothing Then
Application.EnableEvents = False
Target.EntireRow.Cut
rngDest2.Insert Shift:=xlDown
Target.EntireRow.Delete
Application.EnableEvents = True
End If
End If
End Sub
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Application.EnableEvents = False
On Error GoTo Xit:
If Target.Column = 11 Then
Cancel = True
Target.Offset(, 2).Value = "IN PROGRESS"
Target.Offset(, 4).Value = Time
ElseIf Target.Column = 12 Then
Cancel = True
Target.Offset(, 1).Value = "COMPLETE"
Target.Offset(, 4).Value = Time
ElseIf Target.Column = 14 Then
Cancel = True
Target.Offset(, -1).Value = "PARTIAL HOLD"
End If
Xit:
Application.EnableEvents = True
End Sub
What can I do to fix this?

Related

Excel VBA dual Worksheet_change events not working

Having trouble executing both Worksheet_Change events correctly. Image below show my results, when modifying column B, column M does nothing. When modifying column L, column N updates as expected but only on row 2. Every other subsequent change to B or M results in N:2 updating to the current time again.
My desired outcome is that when Col B is updated I record a time stamp in Col M and the same when Col L updates that I get a time stamp in Col N.
Example of Excel Error
My current code is here:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Dim rng As Range
Dim rng2 As Range
If Not Intersect(Target, Columns("B"), Target.Parent.UsedRange) Is Nothing Then
On Error GoTo Safe_Exit
For Each rng In Intersect(Target, Columns("B"), Target.Parent.UsedRange)
If CBool(Len(rng.Value2)) And Not CBool(Len(rng.Offset(0, 11).Value2)) Then
rng.Offset(0, 11) = Now
ElseIf Not CBool(Len(rng.Value2)) And CBool(Len(rng.Offset(0, 11).Value2)) Then
rng.Offset(0, 11) = vbNullString
End If
Next rng
Application.EnableEvents = True
End If
ElseIf Not Intersect(Target, Columns("L"), Target.Parent.UsedRange) Is Nothing Then
On Error GoTo Safe_Exit
For Each rng2 In Intersect(Target, Columns("L"), Target.Parent.UsedRange)
If CBool(Len(rng2.Value2)) And Not CBool(Len(rng2.Offset(0, 2).Value2)) Then
rng2.Offset(0, 2) = Now
ElseIf Not CBool(Len(rng2.Value2)) And CBool(Len(rng2.Offset(0, 2).Value2)) Then
rng2.Offset(0, 2) = vbNullString
End If
Next rng2
Application.EnableEvents = True
End If
Safe_Exit:
End Sub
Mock-up, untested, change of code to simplify as you're doing the same actions in two spots:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Dim columnLetter as String
Select Case Target.Column
Case 2 'B
columnLetter = "M"
Case 12 'L
columnLetter = "N"
Case Else
Goto Safe_Exit
End Select
Dim loopRng as Range
For Each loopRng In Range(Cells(Target.Row, Target.Column),Cells(Target.End(xlDown).Row,Target.Column)
If IsEmpty(loopRng) = True And IsEmpty(Cells(loopRng.Row,columnLetter)) = False Then
Cells(loopRng.Row,columnLetter) = Now
ElseIf IsEmpty(loopRng) = False And IsEmpty(Cells(loopRng.Row,columnLetter)) = True Then
Cells(loopRng.Row,columnLetter) = vbNullString
End If
Next loopRng
'Columns(columnLetter).NumberFormat = "yyyy/mm/dd"
Application.EnableEvents = True
Safe_Exit:
Application.EnableEvents = True
End Sub
Note that the IsEmpty() = True is important... when using an If case, you need to specify for each condition, otherwise the implicit detection will fail.
Edit1: Removed Intersect from loop, whereas the range i've listed will need corrected... it at least references a specific range, now.
Edit2: Removing .Offset and working with specific column references in cells().
I tried this version of my original code and it started to work for some reason.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Columns("B"), Target.Parent.UsedRange) Is Nothing Then
On Error GoTo Safe_Exit
Application.EnableEvents = False
Dim rng As Range
For Each rng In Intersect(Target, Columns("B"), Target.Parent.UsedRange)
If CBool(Len(rng.Value2)) And Not CBool(Len(rng.Offset(0, 11).Value2)) Then
rng.Offset(0, 11) = Now
ElseIf Not CBool(Len(rng.Value2)) And CBool(Len(rng.Offset(0, 11).Value2)) Then
rng.Offset(0, 11) = vbNullString
End If
Next rng
End If
If Not Intersect(Target, Columns("L"), Target.Parent.UsedRange) Is Nothing Then
On Error GoTo Safe_Exit
Application.EnableEvents = False
For Each rng In Intersect(Target, Columns("L"), Target.Parent.UsedRange)
If CBool(Len(rng.Value2)) And Not CBool(Len(rng.Offset(0, 2).Value2)) Then
rng.Offset(0, 2) = Now
ElseIf Not CBool(Len(rng.Value2)) And CBool(Len(rng.Offset(0, 2).Value2)) Then
rng.Offset(0, 2) = vbNullString
End If
Next rng
End If
Safe_Exit:
Application.EnableEvents = True
End Sub

Combining 3 Private Sub Worksheet_Change

I am a first time poster and a newby to VBA. So i am hoping i make sense :)
I am trying to combine 3 private subs, but not sure how to code it together.
I have a spreadsheet that has data validation and i want a input box to appear depending on what is selected.
In column "I" is the first set of data validation, with the options of Accepted, Declined and Null invoid, if "Accepted" then nothing, but if either Declined or Null in Void, I would like a pop up box to appear for the user to input $0, and past that to Column "D"
In Column "M" is the next one for data validation, with the only options is blank and Complete. if blank then nothing, but if Complete, i would like a pop up for the user to input the Quotation value, and past that to Column "D".
Thank you in advance.
This is my code
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("I:I")) Is Nothing Then
If Target = "Declined" Then
roww = Target.Row
Application.EnableEvents = False
Cells(roww, "D").Value = Application.InputBox(Prompt:="Updated quoted value to 0", Type:=2)
Application.EnableEvents = True
End If
End If
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("I:I")) Is Nothing Then
If Target = "Null in Void" Then
roww = Target.Row
Application.EnableEvents = False
Cells(roww, "D").Value = Application.InputBox(Prompt:="Updated quoted value to 0", Type:=2)
Application.EnableEvents = True
End If
End If
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("M:M")) Is Nothing Then
If Target = "Complete" Then
roww = Target.Row
Application.EnableEvents = False
Cells(roww, "D").Value = Application.InputBox(Prompt:="Updated quoted value to the Quotation Value", Type:=2)
Application.EnableEvents = True
End If
End If
End Sub
Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("M:M")) Is Nothing Then
If Target = "Complete" Then
roww = Target.Row
Application.EnableEvents = FALSE
Cells(roww, "D").Value = Application.InputBox(Prompt:="Updated quoted value To the Quotation Value", Type:=2)
Application.EnableEvents = TRUE
End If
ElseIf Not Intersect(Target, Range("I:I")) Is Nothing Then
If Target = "Declined" Then
roww = Target.Row
Application.EnableEvents = FALSE
Cells(roww, "D").Value = Application.InputBox(Prompt:="Updated quoted value To 0", Type:=2)
Application.EnableEvents = TRUE
ElseIf Target = "Null in Void" Then
roww = Target.Row
Application.EnableEvents = FALSE
Cells(roww, "D").Value = Application.InputBox(Prompt:="Updated quoted value To 0", Type:=2)
Application.EnableEvents = TRUE
End If
End If
End Sub
see this official docs.

Merge cells doesn't work after locking and unlocking other cell

I've got a sheet in which I'm trying to merge some cells based on CX cell value. CX cell is also dynamically locked/unlocked based on BX cell value. Although locking/unlocking works fine, I get 1004 error when I'm trying to merge cells with line:
Range(Cells(Target.Row, i), Cells(Target.Row + Target.Value - 1, i)).Merge
While code is below.
Option Explicit
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Not Intersect(Target, Range("B14:B50")) Is Nothing And Sh.Name <> "Dane" Then
Dim pass As String
pass = "" 'set the password. Otherwise, protection/unprotection is done without a pass
If Target.Cells.Count > 1 Then Exit Sub
ActiveSheet.Unprotect pass
If Target.Value = "Unlocked" Then
Target.Offset(0, 1).Locked = False
Else
Target.Offset(0, 1).Value = 0
Target.Offset(0, 1).Locked = True
End If
ActiveSheet.Protect pass
End If
If Not Intersect(Target, Range("C14:C50")) Is Nothing And Sh.Name <> "Dane" Then
Dim i As Long
Application.DisplayAlerts = False
For i = 1 To 8 Step 1
If i <> 6 And i <> 7 And Cells(Target.Row, i).MergeCells Then
Cells(Target.Row, i).UnMerge
End If
Next i
If Target.Value <> 0 Then
For i = 1 To 8 Step 1
If i <> 6 And i <> 7 Then
Range(Cells(Target.Row, i), Cells(Target.Row + Target.Value - 1, i)).Merge
End If
Next i
End If
Application.DisplayAlerts = True
End If
End Sub
Okay. So with #FaneDuru comments, I've been able to figure out the issue. Sheet protection was causing the problem, so I had to unprotect and reprotect sheet before for loops in second condition. Also, #FaneDuru advised to set EnableEvents = false there, to prevent any infinite loop issue. Below is the fixed code.
Option Explicit
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Not Intersect(Target, Range("B14:B50")) Is Nothing And Sh.Name <> "Dane" Then
Dim pass As String
pass = "" 'set the password. Otherwise, protection/unprotection is done without a pass
If Target.Cells.Count > 1 Then Exit Sub
ActiveSheet.Unprotect pass
If Target.Value = "Unlocked" Then
Target.Offset(0, 1).Locked = False
Else
Target.Offset(0, 1).Value = 0
Target.Offset(0, 1).Locked = True
End If
ActiveSheet.Protect pass
End If
If Not Intersect(Target, Range("C14:C50")) Is Nothing And Sh.Name <> "Dane" Then
Dim i As Long
Application.DisplayAlerts = False
Application.EnableEvents = False
ActiveSheet.Unprotect pass
For i = 1 To 8 Step 1
If i <> 6 And i <> 7 And Cells(Target.Row, i).MergeCells Then
Cells(Target.Row, i).UnMerge
End If
Next i
If Target.Value <> 0 Then
For i = 1 To 8 Step 1
If i <> 6 And i <> 7 Then
Range(Cells(Target.Row, i), Cells(Target.Row + Target.Value - 1, i)).Merge
End If
Next i
End If
ActiveSheet.Protect pass
Application.EnableEvents = True
Application.DisplayAlerts = True
End If
End Sub
However, I'm still wondering why I need to unprotect the sheet to edit unlocked range.

Clearing cells in a table in excel when one cell is cleared

I have a table from A12 to AO29. The table headers are in row13.
I am working on a macro that deletes data in column D, E and I when the cell in column B is changed or deleted. The code below works fine, except that it is not deleting the data column D. Column D has a data validation list.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = True
If Not Intersect(Target, Range("H6")) Is Nothing Then
Application.EnableEvents = False
Range("H8") = vbNullString
Range("H7") = vbNullString
Application.EnableEvents = True
End If
If Not Intersect(Target, Range("$H6")) Is Nothing Then
Range("A12:B29").ClearContents
Range("D12:E29").ClearContents
Range("I12:I29").ClearContents
Range("A33:F50").ClearContents
Range("J33:J50").ClearContents
Range("A54:H71").ClearContents
Range("L54:L71").ClearContents
Range("A75:H92").ClearContents
Range("L75:L92").ClearContents
Range("A96:E113").ClearContents
Range("I96:I113").ClearContents
Range("A117:B134").ClearContents
Range("F117:F134").ClearContents
Range("A138:C156").ClearContents
Range("G138:G159").ClearContents
Range("A160:C177").ClearContents
Range("G160:G177").ClearContents
Range("A181:C198").ClearContents
Range("G181:G198").ClearContents
End If
If Target.Count > 1 Then Exit Sub
If Not Intersect(Target, Range("A12:A29")) Is Nothing Then
On Error GoTo haveError
Application.EnableEvents = False
If Target.Column = 1 Then Target.Offset(0, 1).clearcontent
Target.EntireRow.Range("B1,D1,E1,I1").ClearContents
Application.EnableEvents = True
End If
If Not Intersect(Target, Range("B12:B29")) Is Nothing Then
On Error GoTo haveError
Application.EnableEvents = False
If Target.Column = 1 Then Target.Offset(0, 1).clearcontent
Target.EntireRow.Range("D1,E1,I1").ClearContents
End If
If Not Intersect(Target, Range("D12:D29")) Is Nothing Then
On Error GoTo haveError
Application.EnableEvents = False
If Target.Column = 1 Then Target.Offset(0, 1).clearcontent
Target.EntireRow.Range("E1,I1").ClearContents
End If
If Not Intersect(Target, Range("E12:E29")) Is Nothing Then
On Error GoTo haveError
Application.EnableEvents = False
If Target.Column = 1 Then Target.Offset(0, 1).clearcontent
Target.EntireRow.Range("I1").ClearContents
Application.EnableEvents = True
End If
Exit Sub
haveError:
Application.EnableEvents = True
This would be easier to manage:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim c As Range
If Target.Count > 1 Then Exit Sub
If Not Intersect(Target, _
Me.Range("A12:B29,D12:D29,E12:E29")) Is Nothing Then
On Error GoTo haveError
Application.EnableEvents = False
For Each c in Target.EntireRow.Range("B1,D1,E1,I1").Cells
If c.Column > Target.Column Then c.ClearContents
Next c
Application.EnableEvents = True
End If
Exit Sub
haveError:
Application.EnableEvents = True
End Sub
Note when using Range() in the context of EntireRow, the range is relative to the single row.
When you're checking the b12-b29 range, you're not unionizing your ranges so the call to clear contents only affects the last range you set it to which would be the i column.
You could also condense this down drastically by replacing it with one line like this
If Not Intersect(Target, Range("b12", "b29")) Is Nothing Then
Set rngDB = Union(Range("d" & Target.Row), Range("e" & Target.Row), Range("i" & Target.Row))
rngDB.ClearContents
End If

Selection Change affecting cells outside of range

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Const Col As Long = 2
If Not Intersect(Target, Range("L7:L98")) Is Nothing Then
Application.EnableEvents = False
Target.Value = "T"
Target.Offset(, 1).Resize(, Col).ClearContents
Application.EnableEvents = True
End If
If Not Intersect(Target, Range("M7:M98")) Is Nothing Then
Application.EnableEvents = False
Target.Value = "I"
Target.Offset(, 1).ClearContents
Target.Offset(, -1).ClearContents
Application.EnableEvents = True
End If
If Not Intersect(Target, Range("N7:N98")) Is Nothing Then
Application.EnableEvents = False
Target.Value = "D"
Range(Target.Offset(, -1), Target.Offset(, -2)).ClearContents
Application.EnableEvents = True
End If
End Sub
This code is causing a slight problem for me. Any time I select an entire row within the ranges, every cell within the range gets changed to "T". Given the consistency of the code, if I delete the string with "T", then the entire row would be filled with "I"
What can be adjusted to trigger only if cells within the range are selected?
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Const Col As Long = 2
If Target.Count > 1 Then
Exit Sub
End If
Added this to the top of the code, it will now exit the Sub if more than one cell is selected even if one of the selected cells are within the appropriate range.
After checking to see if the Selection intersects with the various ranges, only deal with the part of Target that intersects with the various ranges.
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Const Col As Long = 2
If Not Intersect(Target, Range("L7:L98")) Is Nothing Then
Application.EnableEvents = False
With Intersect(Target, Range("L7:L98"))
.Value = "T"
.Offset(, 1).Resize(, Col).ClearContents
End With
End If
If Not Intersect(Target, Range("M7:M98")) Is Nothing Then
Application.EnableEvents = False
With Intersect(Target, Range("M7:M98"))
.Value = "I"
.Offset(, 1).Resize(, Col).ClearContents
End With
End If
If Not Intersect(Target, Range("N7:N98")) Is Nothing Then
Application.EnableEvents = False
With Intersect(Target, Range("N7:N98"))
.Value = "D"
.Offset(, 1).Resize(, Col).ClearContents
End With
End If
Application.EnableEvents = True
End Sub
Optional Alternative:
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Const Col As Long = 2
If Not Intersect(Target, Range("L7:L98")) Is Nothing Then
Application.EnableEvents = False
With Intersect(Target, Range("L7:L98"))
.Value = "T"
.Offset(, 1).Resize(, Col).ClearContents
End With
ElseIf Not Intersect(Target, Range("M7:M98")) Is Nothing Then
Application.EnableEvents = False
With Intersect(Target, Range("M7:M98"))
.Value = "I"
.Offset(, 1).Resize(, Col).ClearContents
End With
ElseIf Not Intersect(Target, Range("N7:N98")) Is Nothing Then
Application.EnableEvents = False
With Intersect(Target, Range("N7:N98"))
.Value = "D"
.Offset(, 1).Resize(, Col).ClearContents
End With
End If
Application.EnableEvents = True
End Sub

Resources