This question was asked and answered back in 2010 but when I follow the directions of the venerable Mr. Buggabill and then run the macro (by editing the target cell) Excel promptly crashes. The code looks like this:
Private Sub Worksheet_Change(ByVal target As Range)
If target.Address = "$A$1" Then
ActiveWorkbook.Worksheets("Sheet2").Range(target.Address).Value = target.Value
End If
End Sub
I created one version of the macro under Sheet1 (which pushes the target value to A1 on Sheet2) and another version of the macro under Sheet2 (which does the reverse). With only one macro in place this works fine but my intent is to be able to enter a value on either sheet and have the new value propagated into both input cells. Excel crashes because it's a circular reference, right? Is there a way around this?
I suspect that it's not a circular reference, but rather a stack overflow ;)
You might consider turning off eventing inside the execution of your macros.
Application.EnableEvents = False
...
Application.EnableEvents = True
This way, the other event handler won't get called when you're poking values onto the other sheet.
Just add in another if inside the first one.
Private Sub Worksheet_Change(ByVal target As Range)
If target.Address = "$A$1" Then
If ActiveWorkbook.Worksheets("Sheet2").Range(target.Address).Value <> target.Value
ActiveWorkbook.Worksheets("Sheet2").Range(target.Address).Value = target.Value
End If
End If
End Sub
That should stop it from trying to execute when the two values already match. It checks to see if they are the same before doing the update.
Related
How can I automatically execute an Excel macro each time a value in a particular cell changes?
Right now, my working code is:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("H5")) Is Nothing Then Macro
End Sub
where "H5" is the particular cell being monitored and Macro is the name of the macro.
Is there a better way?
Your code looks pretty good.
Be careful, however, for your call to Range("H5") is a shortcut command to Application.Range("H5"), which is equivalent to Application.ActiveSheet.Range("H5"). This could be fine, if the only changes are user-changes -- which is the most typical -- but it is possible for the worksheet's cell values to change when it is not the active sheet via programmatic changes, e.g. VBA.
With this in mind, I would utilize Target.Worksheet.Range("H5"):
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("H5")) Is Nothing Then Macro
End Sub
Or you can use Me.Range("H5"), if the event handler is on the code page for the worksheet in question (it usually is):
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("H5")) Is Nothing Then Macro
End Sub
I spent a lot of time researching this and learning how it all works, after really messing up the event triggers. Since there was so much scattered info I decided to share what I have found to work all in one place, step by step as follows:
1) Open VBA Editor, under VBA Project (YourWorkBookName.xlsm) open Microsoft Excel Object and select the Sheet to which the change event will pertain.
2) The default code view is "General." From the drop-down list at the top middle, select "Worksheet."
3) Private Sub Worksheet_SelectionChange is already there as it should be, leave it alone. Copy/Paste Mike Rosenblum's code from above and change the .Range reference to the cell for which you are watching for a change (B3, in my case). Do not place your Macro yet, however (I removed the word "Macro" after "Then"):
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("H5")) Is Nothing Then
End Sub
or from the drop-down list at the top left, select "Change" and in the space between Private Sub and End Sub, paste If Not Intersect(Target, Me.Range("H5")) Is Nothing Then
4) On the line after "Then" turn off events so that when you call your macro, it does not trigger events and try to run this Worksheet_Change again in a never ending cycle that crashes Excel and/or otherwise messes everything up:
Application.EnableEvents = False
5) Call your macro
Call YourMacroName
6) Turn events back on so the next change (and any/all other events) trigger:
Application.EnableEvents = True
7) End the If block and the Sub:
End If
End Sub
The entire code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("B3")) Is Nothing Then
Application.EnableEvents = False
Call UpdateAndViewOnly
Application.EnableEvents = True
End If
End Sub
This takes turning events on/off out of the Modules which creates problems and simply lets the change trigger, turns off events, runs your macro and turns events back on.
Handle the Worksheet_Change event or the Workbook_SheetChange event.
The event handlers take an argument "Target As Range", so you can check if the range that's changing includes the cell you're interested in.
I prefer this way, not using a cell but a range
Dim cell_to_test As Range, cells_changed As Range
Set cells_changed = Target(1, 1)
Set cell_to_test = Range( RANGE_OF_CELLS_TO_DETECT )
If Not Intersect(cells_changed, cell_to_test) Is Nothing Then
Macro
End If
I have a cell which is linked to online stock database and updated frequently. I want to trigger a macro whenever the cell value is updated.
I believe this is similar to cell value change by a program or any external data update but above examples somehow do not work for me. I think the problem is because excel internal events are not triggered, but thats my guess.
I did the following,
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheets("Symbols").Range("$C$3")) Is Nothing Then
'Run Macro
End Sub
How can I automatically execute an Excel macro each time a value in a particular cell changes?
Right now, my working code is:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("H5")) Is Nothing Then Macro
End Sub
where "H5" is the particular cell being monitored and Macro is the name of the macro.
Is there a better way?
Your code looks pretty good.
Be careful, however, for your call to Range("H5") is a shortcut command to Application.Range("H5"), which is equivalent to Application.ActiveSheet.Range("H5"). This could be fine, if the only changes are user-changes -- which is the most typical -- but it is possible for the worksheet's cell values to change when it is not the active sheet via programmatic changes, e.g. VBA.
With this in mind, I would utilize Target.Worksheet.Range("H5"):
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("H5")) Is Nothing Then Macro
End Sub
Or you can use Me.Range("H5"), if the event handler is on the code page for the worksheet in question (it usually is):
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("H5")) Is Nothing Then Macro
End Sub
I spent a lot of time researching this and learning how it all works, after really messing up the event triggers. Since there was so much scattered info I decided to share what I have found to work all in one place, step by step as follows:
1) Open VBA Editor, under VBA Project (YourWorkBookName.xlsm) open Microsoft Excel Object and select the Sheet to which the change event will pertain.
2) The default code view is "General." From the drop-down list at the top middle, select "Worksheet."
3) Private Sub Worksheet_SelectionChange is already there as it should be, leave it alone. Copy/Paste Mike Rosenblum's code from above and change the .Range reference to the cell for which you are watching for a change (B3, in my case). Do not place your Macro yet, however (I removed the word "Macro" after "Then"):
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("H5")) Is Nothing Then
End Sub
or from the drop-down list at the top left, select "Change" and in the space between Private Sub and End Sub, paste If Not Intersect(Target, Me.Range("H5")) Is Nothing Then
4) On the line after "Then" turn off events so that when you call your macro, it does not trigger events and try to run this Worksheet_Change again in a never ending cycle that crashes Excel and/or otherwise messes everything up:
Application.EnableEvents = False
5) Call your macro
Call YourMacroName
6) Turn events back on so the next change (and any/all other events) trigger:
Application.EnableEvents = True
7) End the If block and the Sub:
End If
End Sub
The entire code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Me.Range("B3")) Is Nothing Then
Application.EnableEvents = False
Call UpdateAndViewOnly
Application.EnableEvents = True
End If
End Sub
This takes turning events on/off out of the Modules which creates problems and simply lets the change trigger, turns off events, runs your macro and turns events back on.
Handle the Worksheet_Change event or the Workbook_SheetChange event.
The event handlers take an argument "Target As Range", so you can check if the range that's changing includes the cell you're interested in.
I prefer this way, not using a cell but a range
Dim cell_to_test As Range, cells_changed As Range
Set cells_changed = Target(1, 1)
Set cell_to_test = Range( RANGE_OF_CELLS_TO_DETECT )
If Not Intersect(cells_changed, cell_to_test) Is Nothing Then
Macro
End If
I have a cell which is linked to online stock database and updated frequently. I want to trigger a macro whenever the cell value is updated.
I believe this is similar to cell value change by a program or any external data update but above examples somehow do not work for me. I think the problem is because excel internal events are not triggered, but thats my guess.
I did the following,
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheets("Symbols").Range("$C$3")) Is Nothing Then
'Run Macro
End Sub
I am trying to activate a macro by clicking in a cell.
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Selection.Count = 1 Then
If Not Intersect(Target, Range("B37")) Is Nothing Then
Worksheets("DaysEditor").Activate
Sheets("DaysEditor").Columns("C:LY").Hidden = False
Sheets("DaysEditor").Columns("C:EX").Hidden = True
Sheets("DaysEditor").Range("A1").Select
End If
End If
End Sub
This code works on a cell that doesn't have a formula but will not work on cells with a formula in them.
A few minor tweaks I would change with your code. Firstly, if you are going to make multiple calls to a worksheet, I suggest that you either make a variable of it or use it within a With <obj> statement.
Worksheets() is essentially a function. Every time you use it it has to get the function's "value" - hence not the most efficient way of doing things.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Address = "$B$37:$C$37" Then
With Worksheets("DaysEditor")
.Columns("C:LY").Hidden = False
.Columns("C:EX").Hidden = True
.Activate
.Range("A1").Select
End With
End If
End Sub
Generally I advise against using the Activate method. But since you appear to actually want to be on the worksheet when the code runs then it's not a big deal here. Just remember that Activate is not necessary for the remainder of your code to function.
One last tweak is that I moved your Activate method after you hide/unhide the columns. Probably not a big deal either, but no need to watch the screen redraw unnecessarily.
Thanks to #K.Davis he helped me figure out that the problem was the that cell I was attaching this to was a merged cell and that was the problem. I changed the Selection.Count = 1 to Selection.Count = 2 and the code works perfectly!
I currently have an HMI that communicates with Excel through a DDE connection.
If I update values in the HMI then the values are updated in the spreadsheet of Excel and vice versa. Which is exactly what I want. However, I created a VBA code that will also update values in the spreadsheet when values are changed in the HMI. This VBA code does not run though if I change the values through the HMI but will run if I manually change them in Excel.
Is there something that I am not considering?
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Application.Intersect(Range("K1:K3"), Range(Target.Address)) Is Nothing Then
Call UpdateDateandTime
End If
End Sub
Sub UpdateDateandTime()
MsgBox "yes"
End Sub
as a crude workaround, If only three cells are involved, may create some simple formula in other cells involving the target cells (if not already exists) and use Worksheet_Calculate() event do the processing. Something like,
Public VarK1, VarK2, Vark3
Private Sub Worksheet_Calculate()
If VarK1 <> Range("K1").Value Or VarK2 <> Range("K2").Value Or Vark3 <> Range("K3").Value Then
VarK1 = Range("K1").Value
VarK2 = Range("K2").Value
Vark3 = Range("K3").Value
'Call the required process
End If
End Sub
though other direct methods involving DDE may be also be available to do the same and may please research/wait further for more appropriate the commands. Another workaround way is to use Application.OnTime method.
I have two macros in a worksheet. The first one check whether certain cells are addressed and have certain values then runs another macro. The following code is used for this:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("K10:K1000")) Is Nothing And Target.Value = "Trapezoidal roof 0.6mm and above" Or Target.Value = "LightBox ballasted" Then
Application.ScreenUpdating = False
Call PPAPricePerkWp
End If
End Sub
This works fine on it's own.
The second macro is run when a button is clicked. This macro copies and pastes cells/rows to other parts of the spreadsheet.
When the macro is run I get the error Runtime error 7 - out of memory and it breaks on the above bit of code.
Is there another way I can check whether cells in a certain column are addressed and have certain values and won't lead to the above error?
you might want to disable events before you call your subroutine, so that the Worksheet_Change is not being triggered every time you change a cell
Application.EnableEvents = False
Don't forget to turn it back on when you are finished