Activate macro on change with variable row in range - excel

I want to activate a macro on a change in a range.
The following code works fine except I want a variable last row (Where B100 currently is).
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("B1:B100")) Is Nothing Then
MsgBox "Updating sheets"
Call Thickborders2
End If
End Sub
The B100 in the range is dependent on the last row with text in it.

You can borrow a worksheet trick to find the last row with text in it.
=MATCH("zzz", B:B)
The above returns the last row in column B with a text value.
Private Sub Worksheet_Change(ByVal Target As Range)
dim m as variant
m = application.match("zzz", columns("B"))
if iserror(m) then m = 1
If Not Intersect(Target, Range("B1").resize(m, 1)) Is Nothing Then
MsgBox "Updating sheets"
Call Thickborders2
End If
End Sub
I strongly recommend adding error control (on error goto <label>) and disabling event triggers (application.enableevents = false). Remember to re-enable events before exiting the sub.

As I said in my comment on the OP - Worksheet_Change on its own won't work as it will calculate the last cell based on the data just entered.
This code calculates the last cell when you move cells (I tried on the Calculate event but that happens after you've added the data so same problem as the Change event).
Option Explicit
Private rLastCell As Range
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Set rLastCell = Cells(Rows.Count, 2).End(xlUp)
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range(Cells(1, 2), rLastCell)) Is Nothing Then
MsgBox "Updating sheets"
Call Thickborders2
End If
End Sub
The first two lines must be at the very top of the module.

Building on comments from Taazar and L42 try:
Private Sub Worksheet_Change(ByVal Target As Range)
LastCell = Activesheet.Usedrange.Rows.Count
If Not Intersect(Target, Range("B1:B" & LastCell)) Is Nothing Then
MsgBox "Updating sheets"
Call Thickborders2
End If
End Sub
Where Activesheet should be replaced by the sheetname you're checking.

Related

Target.Adress is a mutiple cell range selected individually

I have the following code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$N$16" Then
Sheet3.Unprotect ""
Call QuantityisActivated(Target)
Sheet3.Protect ""
End If
End Sub
How can i use the same code for multiple Target.Adress for example, I want here from N16 to N30 range of cells
Sub QuantityisActivated(Target)
MsgBox "This is a sample box"
End Sub
The following can be used to only fire the QuantityisActivated if cells within the range are changed:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rng As Range, c As Range
Set rng = Intersect(Target, Range("N16:N30"))
If Not rng Is Nothing Then
'If you want it to run on each cell withing the range..
For Each c In rng.Cells
Call QuantityisActivated(c)
Next
'Or if you want it to run once, if any cell in range is affected
Call QuantityisActivated(rng)
End If
End Sub
I've included two possible ways of dealing with the affected range - either at a cell by cell level, or as an entire range as it's not clear which you'd prefer from your question.

Worksheet Change: If value of cell in certain range >c8 -> MsgBox and if value in other cell (that has function in it) > 300 -> MsgBox

I want a worksheet change macro, that pops up a Messagebox whenever a value higher than 8 is put in one of the cells in range (F14:J26) and if a value greater than 300 is put in cell C37.
My problem is that cell C37 is not filled out manually but has a formula in it so it is a calculation of two other cells. And I think excel doesn't recognize this as a value and therefore doesn't do anything whenever the result in that cell is higher than 300.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Application.Intersect(Target, Range("F14:J26")) Is Nothing Then
If Target.Value > 8 Then
MsgBox "Was that accepted?"
End If
End If
If Not Application.Intersect(Target, Range("C37")) Is Nothing Then
If Target.Value > 300 Then
MsgBox "Was that accepted?"
End If
End If
End Sub
The first part of the code works as it should. But the second part as explained above doesn't. I also tried to split it in two separate codes but that shows a bug. Any help on this would be very much appreciated!
In addition to Gerrit's anwser I recommend to extend it in the following way, so it doesn't fail if someone pastes a data range into F14:J26.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim AffectedRng As Range
Set AffectedRng = Application.Intersect(Target, Range("F14:J26"))
Dim FoundInvalidData As Boolean
If Target.Parent.Range("C37").Value > 300 Then
FoundInvalidData = True
ElseIf Not AffectedRng Is Nothing Then
Dim Cel As Range
For Each Cel In AffectedRng.Cells
If Cel.Value > 8 Then
FoundInvalidData = True
Exit For
End If
Next Cel
End If
If FoundInvalidData Then
MsgBox "Was that accepted?"
End If
End Sub
You have two (maybe more) possible options:
Use the "Worksheet_Calculate"-event, instead of the "Worksheet_Change"-event.
If the formular in C37 is fixed, don't monitor C37 but the source-cells instead.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Application.Intersect(Target, Range("F14:J26")) Is Nothing Then
If Target.Value > 8 OR Range("C37").Value > 300 Then
MsgBox "Was that accepted?"
End If
End If
End Sub

VBA getting the column number from the Target in a worksheet change

I have a table of values that I need to fill out through a worksheet change function.
What I am trying to do is change a cell in columns B-G, depending on where the target is.
Private Sub Worksheet_Change(ByVal Target As Range)
If (Not Intersect(Target, Range(Cells(12, 2), Cells(14, 7))) Is Nothing) Then
Cells(16,Application.WorksheetFunction.Column(Target))="Hello"
End If
End Sub
I have similar bits of code in the same worksheet_change sub that work fine when I use Target.Offset(1,0) but since my possible target range is in more than 1 Row, I don't know how to make it so that it is always row 16 and the same column as the target....
You need to deal with situations where Target is more than a single cell and disable event handling so when you change a value on the worksheet, the Worksheet_Change doesn't try to run on top of itself.
This will put 'hello' into the cell immediately to the right of any cell within B:G that changes; essentially you would be adding 'hello' to columns C:H on the associated row of each cell in Target.
Private Sub Worksheet_Change(ByVal Target As Range)
if not intersect(target, Range(Cells(12, "B"), Cells(14, "G"))) is nothing then
on error goto safe_exit
application.enableevents = false
dim t as range
for each t in intersect(target, Range(Cells(12, "B"), Cells(14, "G")))
t.Offset(1,0) = "hello"
next t
End If
safe_exit:
application.enableevents = true
End Sub

Excel VBA Click Cell to Fire Macro - Not working with Merged Cells

I am using the code below to fire a macro on the click of a cell. The cell in question is a header "Mitch's Macro" but it on merged cells B5 through J5. I have tried naming this merged range to MITCH, but it still doesnt run on click... Any ideas? Thank you in advance!
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Selection.Count = 1 Then
If Not Intersect(Target, Range("MITCH")) Is Nothing Then
MsgBox ("Hello World")
End If
End If
End Sub
The problem is Selection.Count = 1.
The merged cells have more than one cells so once you select any cell in the merged area, the code doesn't get executed.
Please give this a try...
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, Range("MITCH")) Is Nothing Then
MsgBox ("Hello World")
End If
End Sub
Edit:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim rng As Range
Set rng = Range("MITCH")
If Target.CountLarge > rng.Cells.Count Then Exit Sub
If Not Intersect(Target, rng) Is Nothing And Target.Cells(1).Address = rng.Cells(1).Address Then
MsgBox ("Hello World")
End If
End Sub
After a little more thinking I realised that most answers have a few drawbacks, and I think this is what we're really after:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim rng As Range
Set rng = Range("MITCH")
If Target.Address = rng.MergeArea.Address Then 'check if what's selected matches the named range entirely
MsgBox ("Hello World")
End If
End Sub
As this checks whether the cells you have selected perfectly map onto the named area - specifically the MergeArea of the named range.
Matching with Intersect just checks if the selection contains the named Range
Matching by TL cell means any selection with the same TL as the named Range will also return a positive. E.g, if [B2:D3] is your merged named range, then matching by [B2] will return positive if [B2:D3] is selected (as expected), but also when [B2:XX100] is selected
This code only returns positive when the areas are identical, i.e. only the merged cell is selected.
If you have named the range you could use the code below
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim tName As String
On Error Resume Next
tName = Target.Name.Name
On Error GoTo 0
If Len(tName) > 0 Then
If tName = "MITCH" Then
MsgBox ("Hello World")
End If
End If
End Sub

Type Mismatch error with cell selection

I created this basic worksheet_change function which monitors column B. If a cell in column B gets deleted, it updates the delete in column C as well. The only issue is that since this is a change event, when more then 2 cells are altered at once, it throws a type mismatch error. This is because its comparing the Target.Address(s) to "" which is a type mismatch. How can I fix this to only run if only a single cell is select and not crash on a multiple cell select?
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Set KeyCells = Range("B2:B51")
If Not Application.Intersect(KeyCells, Range(Target.Address)) Is Nothing Then
If Range(Target.Address).Value = "" Then
Range("C" & Target.Row).Clear
End If
End If
End Sub
To simply check if the Target Range changed is more than one cell, you can simply count the cells in the range.
As mentioned in the comment, right after you declare the sub, you can add:
If Target.Count > 1 Then Exit Sub.
Alternatively, of course you could do, If Target.Count = 1 Then ...
Edit: Per your question above, you can do this to make sure events are on:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count > 1 Then
Application.EnableEvents = True
Exit Sub
End If
' Code here that will run, if the Target is just one cell
End Sub

Resources