Run Macro when cell result changes by formula - excel

What I am needing: A macro to be triggered, let's call the macro "MacroRuns", whenever cell C3 returns a different value than it currently has, based on its FORMULA, NOT based on manually typing a different value.
I have spent all day reading through and attempting every "solution" on the first two pages of my google search on this topic. So far, nothing seems to work for me. Please help!!! I would very much appreciate it!
Example:
I have now tried this but it corrupts my file after it works a few times.
Private Sub Worksheet_Calculate()
If Range("E3") <> Range("C3").Value Then
Range("E3") = Range("B3").Value
MsgBox "Successful"
End If
End Sub

Module1, Sheet1 (Calculate), ThisWorkbook (Open)
Highlights
When the workbook opens, the value from C3 is read into the public
variable TargetValue via TargetStart.
When the value in C3 is being calculated, TargetCalc is activated
via the calculate event.If the current value in C3 is different than TargetValue, MacroRuns is triggered and TargetValue is updated with the value in C3.
The Code
Module1
Option Explicit
Public TargetValue As Variant
Private Const cTarget As String = "C3"
Sub TargetCalc(ws as Worksheet)
If ws.Range(cTarget) <> TargetValue Then
MacroRuns
TargetValue = ws.Range(cTarget).Value
End If
End Sub
Sub TargetStart()
TargetValue = Sheet1.Range(cTarget).Value
End Sub
Sub MacroRuns()
MsgBox "MacroRuns"
End Sub
ThisWorkbook
Option Explicit
Private Sub Workbook_Open()
TargetStart
End Sub
Sheet1
Option Explicit
Private Sub Worksheet_Calculate()
TargetCalc Me
End Sub

Right. I have a nugget to add in here, something that completely frustrated me upon trying Ferdinando's code (which by itself is very neat, thank you, Ferdinando!!)
The main point is - if you are going to be using anything beyond just a messagebox (MsgBox "Cell has changed.") you need to add the following lines above AND below this line(otherwise the Excel will simply crash constantly due to endlessly trying to do the same). Don't ask me why this is, but I finally-finally solved my problem with this. So here are the lines:
If Value1 <> Value2 Then
(ADD THIS:) Application.EnableEvents = False
MsgBox "Cell has changed."
(I call a macro running a query from MySQL instead of MsgBox)
(AND ADD THIS:) Application.EnableEvents = True
Hope this helps anyone in the situation I was in!!

If i understood your question you can try this code:
1)Right-click the Sheet tab and then click View Code
copy this code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Value1 As Variant
Static Value2 As Variant
Value1 = Range("C3").value
If Value1 <> Value2 Then
MsgBox "Cell has changed."
End If
Value2 = Range("C3").value
End Sub
i tried this one:
in cell C3 i have wrote =SUM(A1:B1)
when i try to change value in this cells also C3 change and i get the msgBox
Hope this helps
EDIT the code to answer # MD Ismail Hosen
if i understood your problem you can try this example code:
Private Sub Worksheet_Change(ByVal Target As Range)
'in this code i have used two range on the same row, but you can change as
'you want.
'In my case, the range that i check is Range("A1:C1") and the RANGE that i 'save old value is
'RANGE("F1:H1") F1 is the sixth column.
Dim counter As Byte
Dim sizeRange As Byte
sizeRange = 3 ' my size range
For counter = 1 To sizeRange
'on the left i check Range("A1:C1").On the right i check The Range("F1:H1")
If Cells(1, counter) <> Cells(1, counter + 5) Then 'counter start from 1
MsgBox "Range Changed"
Range("A1:C1").Copy Destination:=Range("F1:H1") ' use other code to copy the range
Exit For
End If
Next counter
End Sub
If you have a formula in your range ("A1:C1") you have to use this code to copy the new range value A1:C1 in F1:H1 else you get the error(loop the macro).
'TO use this code if you have formula in the cells.
Range("A1:C1").Select
Selection.Copy
Range("F1").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Hope this helps.

Related

CHANGE vs CALCULATE in Excel VBA Worksheet event - not triggered by formula values updates

I need to compare two cells: A1 and C1.
If A1 <> C1 Then run some code.
A1's content is a formula dependent cell (from another sheet, same workbook).
C1's content is static, only changing at the end of the macro run.
Issue:
Having an issue with catching Worksheet_Change(ByVal Target As Range) and Worksheet_Calculate() event when the cells contents are changed, as a result of formulas coming from other sheets (same workbook): when A1's content is updated (by formula), event CHANGE nor CALCULATE will catch this change.
Unless I directly key-in in the target sheet any changes, those formula-updated-result cells won't trigger those events, hence not being able to run associated macros 1 and 2.
I have checked out some suggestions from https://stackoverflow.com/search?q=%5Bvba%5D+WORKSHEET_CHANGE&s=ceca4078-9061-4cfb-ae34-f57285b98d7d, but couldn't fix it.
Any ideas or suggestions? Higly appreciated.
Private Sub Worksheet_Change(ByVal Target As Range)
Set Target = Range("a1")
Dim my_Target1 As Variant
Dim my_Target2 As Variant
my_Target1 = Cells(1, 1).Value
my_Target2 = Cells(1, 3).Value
If Not my_Target1 = my_Target2 Then
Call macro1
MsgBox ("end of update routine")
Else: Call macro2
End If
Exit Sub
End Sub
----- here goes the CALCULATE event code----
Private Sub Worksheet_Calculate()
Dim my_Target1 As Variant
Dim my_Target2 As Variant
my_Target1 = Cells(1, 1).Value
my_Target2 = Cells(1, 3).Value
If Not my_Target1 = my_Target2 Then
Call macro1
MsgBox ("end of update routine")
Else: Call macro2
End If
Exit Sub
End Sub
NOTE - I have tried 2 different scenarios:
(1) scenario OK (successful), if the formulas are fed by new data that is keyed in directly into the workbook;
(2) scenario KO (not successful), if the formulas are fed by new data that is coming from an online external source;
i could capture the event with the Workbook_SheetChange(ByVal Sh As Object, _ ByVal Source As Range)
thank you all for your help.

How to copy entire row from worksheet to another worksheet

I'm relatively new to VBA. I have this sub procedure CutePaste, that I call in worksheet_change(ByVal Target As Range), that executes whenever the value in column "F" is changed. My goal is to copy the entire row of the cell changed and paste it into another sheet ("Cast Worked"). My code right now only copies the updated cell and paste that to the new sheet. Please advise how I can copy the entire row of the updated cell.
Sub CutPaste()
If Not Intersect(myTarget, Range("F:F")) Is Nothing Then
ActiveCell.Activate
a = Sheets("Cast Worked").Cells(Rows.Count, "A").End(xlUp).Row + 1
Sheets("Cast Worked").Range("A" & a).Value = ActiveCell.Value
ActiveCell.Offset(1, 0).Select
End If
End Sub
You are close. You can use the Range.Copy method to do this. Furthermore you need to pass the target from the worksheet_change event to your subroutine.
Sub worksheet_change(ByVal Target As Range)
'Pass target range to subroutine
CutPaste(Target)
End Sub
Sub CutPaste(myTarget As Range)
If Not Intersect(myTarget, Range("F:F")) Is Nothing Then
a = Sheets("Cast Worked").Cells(Rows.Count, "A").End(xlUp).Row + 1
Target.EntireRow.Copy Destination:=Sheets("Cast Worked").Range("A" & a)
Target.Offset(1, 0).Select
End If
End Sub
I removed ActiveCell.Activate since setting the active cell to active is superfluous.

Worksheet change VBA

I've been working Worksheet_Change VBA code in Excel as shown below.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A2:A2000")) Is Nothing Then
Call writetag
End If
End Sub
Sub writetag()
ActiveCell.Select
ActiveCell.Offset(0, 1).Select
ActiveCell.Formula = "1st Request"
End Sub
The writetag VBA code alone does its job just fine wherein it would move 1 cell to the right of the active cell and write "1st Request". Then I have the first VBA code - Worksheet_Change - that will trigger the writetag code whenever there are changes made on range A2:A2000.
But it is at this part that the writetag code does not work perfectly. Instead of moving 1 cell to the right, it would move 1 cell to the right and another 1 cell below. So I need to adjust ActiveCell.Offset(0, 1).Select to ActiveCell.Offset(-1, 1).Select just so that it would move to the right cell.
Then after that, I would like to make 3 conditions or Ifs, wherein when I put 1 anywhere on the A2:A2000 range, it will put "1st Request" to its right. If I put 2 anywhere on the range, it will put "2nd Request" to its right, "3rd Request" if I put 3.
Thank you so much for the help.
Remember target is the address of the called cell, in your case suppose you entered in cell A1:
target = [A1] but the problem is that this event fires after the value is changed so after press enter ActiveCell = [A2], then the event is called and the result is
 
ActiveCell.offset (0,1) = [A2] .offset (0,1) = [B2]
so your code is not working, let's try:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A2:A2000")) Is Nothing Then
Call writetag(Target)
End If
End Sub
Sub writetag(rng As Range)
With rng.Offset(0, 1)
Select Case rng.Value2
Case 1
.Formula = "1st Request"
Case 2
.Formula = "2nd Request"
Case 3
.Formula = "3rd Request"
End Select
End With
End Sub
Use following sub when you enter value and press ENTER from keyboard.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A2:A2000")) Is Nothing Then
Call writetag
End If
End Sub
Sub writetag()
Dim curr As Variant
curr = ActiveCell.Offset(-1, 0)
ActiveCell.Offset(-1, 1) = curr & "st Request"
End Sub

Automatically run macro when a value changes as the result of Vlookup

I want MyMacro to run automatically when the cell value in A1 changes according to a vlookup formula. MyMacro copies a row then pastes it to a different section of the worksheet when a condition dependant on the value of A1 is met.
I have tried variations of Target.Address and the following, which have not worked:
Public Sub Worksheet_Calculate(ByVal Target As Range)
Static OldVal As Variant
If Range("A1").Value <> OldVal Then
OldVal = Range("A1").Value
If Not Intersect(Target(1), Range("C1401:I140")) Is Nothing Then
If Range("A1").Value < ActiveSheet.Range("A1").Value Then
Range("C140:I140").Value = Range("B55:H55").Value
ElseIf Range("B55").Value > ActiveSheet.Range("A1").Value Then
Range("C140:I140").Formula = ""
End If
End If
End If
End Sub
Public Sub MyMacro()
Worksheet_Calculate ([C140])
End Sub
With this, MyMacro only works when I manually hit Run Macro after each time A1 changes. How can I get this to be automatic?
Thanks.
If you want to do something when the value of your calculated Cell A1 changes then use the Worksheet_Change event on the relevant worksheet.
(Find the worksheet in the VBA editor and right-click to select "view code")
Sub Worksheet_Change(ByVal Target As Range)
If Not Application.Intersect(Range("$A$1"), Target) Is Nothing Then
... [call your change_routine]
end if
End Sub

How to use VBA code without a macro trigger

I am currently using the following VBA to run a macro when a value chosen from a dropdown changes, and the code works fine:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("D5")) Is Nothing Then
Select Case Range("D5")
Case "2008": Macro1
Case "2015": Macro1
End Select
End If
End Sub
However I would like to run the following event when another cell changes (also a drop down), the code is written to hide columns, this is the snippet of the additional code:
Sub hideColumnsBasedOnConditionZero()
LastColumn = 11 'Last Column
For i = 1 To LastColumn 'Lopping through each Column
'Hide all the columns with the values as 0 in Row 11
If Cells(1, i) = 0 And Cells(1, i) <> "" Then Columns(i).EntireColumn.Hidden = True
Next
End Sub
Can someone please tell me how to achieve this? The second code is valid but I cannot activate it as the first code is using the change function and is specific to another cell.
You can just add it to your first event
Private Sub Worksheet_Change(ByVal Target As Range)
Dim LastColumn As Long
With Me
If Not Intersect(Target, .Range("D5")) Is Nothing Then
Select Case .Range("D5")
Case "2008", "2015": Macro1
End Select
ElseIf Not Intersect(Target, .Range("Your Other Range")) Is Nothing Then
Call hideColumnsBasedOnConditionZero
End If
End With
End Sub

Resources