Got a problem and looking for some advice. I've been using the below code for a while now in Excel, it clears the contents of column B if cell A is empty. It works great, but I now need it to work for a specific range (A6:B35). Any ideas?
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Target.Column = 1 Then
If Target.Validation.Type = 3 Then
Application.EnableEvents = False
Target.Offset(0, 1).ClearContents
End If
End If
exitHandler:
Application.EnableEvents = True
Exit Sub
End Sub
You need to test if the active cell (target) falls in the range A6:A35. Like this:
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If not intersect(target, range("A6:A35")) is nothing then
If Target.Validation.Type = 3 Then
Application.EnableEvents = False
Target.Offset(0, 1).ClearContents
Application.EnableEvents = True
End If
End if
exitHandler:
End Sub
You should also indent your code so it is more readable. It will help with loops and IF statements.
something like
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng1 As Range
Dim rng2 As Range
Set rng1 = Intersect(Target, Range("A6:B35"))
If rng1 Is Nothing Then Exit Sub
Application.EnableEvents = False
For Each rng2 In rng1
If rng2.Validation.Type = 3 Then rng2.Offset(0, 1).ClearContents
Next
Application.EnableEvents = True
End Sub
Related
Can someone please help me with this code. It will insert the current date in H if I do any changes to I.
My problem is that this will not work if for example I fill in I1 with something, and then I drag down for copying in many cells at once. If for example I copy value from I1 once at a time in each cell( I2,I3 ETC) it will work.
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
'Updated by Extendoffice 2017/10/12
Dim xRg As Range, xCell As Range
On Error Resume Next
If (Target.Count = 1) Then
If (Not Application.Intersect(Target, Me.Range("I:I")) Is Nothing) Then _
Target.Offset(0, -1) = Date
Application.EnableEvents = False
Set xRg = Application.Intersect(Target.Dependents, Me.Range("I:I10"))
If (Not xRg Is Nothing) Then
For Each xCell In xRg
xCell.Offset(0, -1) = Date
Next
End If
Application.EnableEvents = True
End If
End Sub
Thank you !
Avoid the unnecessary use of On Error Resume Next. Handle the Error gracefully. I recommend reading THIS once when using Worksheet_Change
Also you have If (Target.Count = 1) Then because of which your code doesn't execute. When you drag, the count increases.
Is this what you are trying?
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Whoa
Dim aCell As Range
Application.EnableEvents = False
If Not Intersect(Target, Range("I:I")) Is Nothing Then
For Each aCell In Target
'~~> Additional blank check for I. So that the date
'~~> is not inserted if the value is deleted. Remove this
'~~> if you want the date to be inserted even when the value is deleted
If Len(Trim(aCell.Value)) <> 0 Then
Range("H" & aCell.Row).Value = Date
Else
'Remove Date?
End If
Next aCell
End If
Letscontinue:
Application.EnableEvents = True
Exit Sub
Whoa:
MsgBox Err.Description
Resume Letscontinue
End Sub
In action:
I want a macro that automatically multiplies a given column by a set number. This number will be different for each column. I am only able to apply it to one column so far. I can't have it done for any other:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Range("B:B")) Is Nothing Then Exit Sub
Application.EnableEvents = False
Target.Value = Target.Value * 300
Application.EnableEvents = True
If Intersect(Target, Range("C:C")) Is Nothing Then Exit Sub
Application.EnableEvents = False
Target.Value = Target.Value * 500
Application.EnableEvents = True
End Sub
Perhaps like this:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.CountLarge > 1 Then Exit Sub
On Error GoTo SafeExit
Application.EnableEvents = False
Dim rng As Range
Set rng = Intersect(Target, Me.Range("B:B")
If Not rng Is Nothing Then
rng.Value = rng.Value * 300
End If
Set rng = Intersect(Target, Me.Range("C:C"))
If Not rng Is Nothing Then
rng.Value = rng.Value * 500
End If
SafeExit:
Application.EnableEvents = True
End Sub
EDIT:
This is probably a better approach if you have more than two columns (and they are contiguous):
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("B:F")) Is Nothing Then
On Error GoTo SafeExit
Application.EnableEvents = False
Dim rng as Range
For Each rng In Intersect(Target, Me.Range("B:F"))
Dim multiplier As Long
Select Case rng.Column
Case 2 ' column B
multiplier = 300
Case 3 ' column C
multiplier = 500
Case 4 ' column D
multiplier = 400
Case 5 ' column E
multiplier = ...
Case 6 ' column F
multiplier = ...
End Select
If IsNumeric(rng.Value) Then
rng.Value = rng.Value * multiplier
End If
Next
End If
SafeExit:
Application.EnableEvents = True
End Sub
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
I am trying to run this worksheet change event for two different columns(A) and (I)...
Private Sub Worksheet_Change(ByVal Target As Range)
Dim A As Range, B As Range, Inte As Range, r As Range
Set A = Range("A:A")
Set Inte = Intersect(A, Target)
If Inte Is Nothing Then Exit Sub
Application.EnableEvents = False
For Each r In Inte
r.Offset(0, 1).Value = Date
Next r
Application.EnableEvents = True
End Sub
This event is something i found on this forum. Its purpose is to make it so whenever data is ever entered into column "a" it auto inputs the date into the cell directly right of it. I want this to happen twice on the worksheet. I can't figure out how to change/add to it. I am trying to get it to run the logic for column A and I on my spreadsheet.
Just expand the range you set to the A variable.
Set A = Range("A:A, I:I")
Rewritten as,
Private Sub Worksheet_Change(ByVal Target As Range)
if not intersect(range("A:A, I:I"), target) is nothing then
'add error control
on error goto safe_exit
'don't do anything until you know something has to be done
dim r as range
Application.EnableEvents = False
For Each r In intersect(range("A:A, I:I"), target)
r.Offset(0, 1).Value = Date 'do you want Date or Now?
Next r
end if
safe_exit:
Application.EnableEvents = True
End Sub
edited after OP's comment
expanding on #Jeeped solution, you can avoid looping:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range
Set rng = Intersect(Range("A:A, I:I"), Target) ' define range of interest
If Not rng Is Nothing Then ' check it's not "nothing"
If WorksheetFunction.CountA(rng) = rng.Count Then 'check for all of its cells being not empty
On Error GoTo safe_exit 'add error control
Application.EnableEvents = False 'don't do anything until you know something has to be done
rng.Offset(, 1).Value = Date 'write Date next to all relevant changed cells
End If
End If
safe_exit:
Application.EnableEvents = True
End Sub
I have a worksheet with values depending on Cell A. If a row in column A contains a value then cells from Columns B through H will be changed accordingly.
If Cell of Column A is empty I want to reset the cells from columns D through F.
I wrote down the following VBA Code
Private Sub Worksheet_Change(ByVal Target As Range)
Dim n As Integer
For n = 5 To 75
Application.EnableEvents = False
If VarType(Cells(n, 1)) = vbEmpty Then
Cells(n, 4).ClearContents
Cells(n, 5).ClearContents
Cells(n, 6).ClearContents
Application.EnableEvents = True
End If
Next n
End Sub
The "FOR" Loop is annoying, and making the Excel to pause for 1 second or more after any entry to any Cell, can anyone help me correct the above code to do what I need to do without the "FOR" loop.
You are using a Worksheet_Change event and you iterating through 70 rows each time something changes.. this is a bad approach for this kind of problem and that's why there is a delay.
Instead, try
Private Sub Worksheet_Change(ByVal Target As Range)
Dim n As Long
If Target.Column = 1 Then
If IsEmpty(Cells(Target.Row, 1)) Then
Range("B" & Target.Row & ":F" & Target.Row).ClearContents
End If
End If
End Sub
this will only clear the cells if you remove a value from column A => when cell in column A is empty
Try this:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i As Integer
If Mid(Target.Address(1, 1), 1, 2) = "$A" Then
If Target.Cells(1, 1).Value = "" Then
For i = 4 To 6
Target.Cells(1, i).Value = ""
Next i
End If
End If
End Sub
Give this a try:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rLook As Range, r As Range, Intr As Range
Set rLook = Range("A5:A75")
Set Intr = Intersect(rLook, Target)
If Intr Is Nothing Then Exit Sub
Application.EnableEvents = False
For Each r In Intr
If r.Value = "" Then
rw = r.Row
Range("D" & rw & ":F" & rw).ClearContents
End If
Next r
Application.EnableEvents = True
End Sub
It should have minimal impact on timing.
Use a range object.
The following line of code will print the address of the Range we'll use to clear the contents. The first cells call gets the upper left corner of the range, the second cells call gets the lower right corner of the range.
Private Sub test()
Debug.Print Range(Cells(5, 4), Cells(75, 6)).Address
End Sub
We apply this to your code like this:
Private Sub Worksheet_Change(ByVal Target As Range)
If VarType(Cells(Target.Row, 1)) = vbEmpty Then
Application.EnableEvents = False
Range(Cells(Target.Row, 4), Cells(Target.Row, 6)).ClearContents
Application.EnableEvents = True
End If
End Sub
One final sidenote: You should use an error handler to make sure events are always enabled when the sub exits, even if an error occurs.
Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo ErrHandler
If VarType(Cells(Target.Row, 1)) = vbEmpty Then
Application.EnableEvents = False
Range(Cells(Target.Row, 4), Cells(Target.Row, 6)).ClearContents
End If
ExitSub:
Application.EnableEvents = True
Exit Sub
ErrHandler:
MsgBox "Oh Noes!", vbCritical
Resume ExitSub
End Sub
You should disable events and cater for multiple cells when using the Change event.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng1 As Range
Dim rng2 As Range
Set rng1 = Intersect(Columns("A"), Target)
If rng1 Is Nothing Then Exit Sub
With Application
.EnableEvents = False
.ScreenUpdating = False
End With
For Each rng2 In rng1.Cells
If IsEmpty(rng2.Value) Then rng2.Offset(0, 1).Resize(1, 5).ClearContents
Next
With Application
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub
For those that need to have data entered in one cell cleared (in a column) when there's a change in another column use this, which is a modification of Gary's Student.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rLook As Range, r As Range, Intr As Range
Set rLook = Range("D:D")
Set Intr = Intersect(rLook, Target)
If Intr Is Nothing Then Exit Sub
Application.EnableEvents = False
For Each r In Intr
If r.Value = "" Then
rw = r.Row
Range("L:L").ClearContents
End If
Next r
Application.EnableEvents = True
End Sub