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.
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 want to confirm with a popup message and sound effect in a protected Excel 2010 worksheet when the values of two cells are the same. I have tried this formula in data validation:
IF(D4=D5,beepnow(),"")
but it does not run. Can anyone assist with the formula or a VBA code replacement instead? Thanks!
Here's a program that will run whenever you change to the worksheet... which may get pretty annoying... You should get the idea though and be able to modify it to fit your needs.
Private Sub Worksheet_Activate()
If Range("D4").Value = Range("D5").Value Then
Beep
MsgBox "Equal", vbInformation, "Check"
End If
End Sub
You should just be able to copy and paste it into your worksheet class.
If you go to the VB COde Window, select the relevant sheet, you can have the following
Private Sub Worksheet_Change(ByVal Target As Range)
If (Range("D4:D4").Cells(1, 1)) = Range("D5:D5").Cells(1, 1)) Then
MsgBox ("Hi")
End If
End Sub
The worksheet activate will run the code when you select this sheet.
The Worksheet_change will run the code when you make a change in this sheet.
IF you want to have the check only when D4/D5 is modified
If Target.Address = "$D$4" Or Target.Address = "$D$5" Then
If (Range("D4:D4").Cells(1, 1)) = Range("D5:D5").Cells(1, 1)) Then
MsgBox ("Hi")
End If
End If
I want to run the bellow macro whenever cell F3 increases. I need this to happen without manual intervention because F3 is increasing due to incoming RTD server data. As it stands, unless I manually update something in my sheet the macro does not run.
Public Prev_Val As Long
Private Sub Worksheet_Change(ByVal Target As Range)
'using a Public variable to store the previous value
If Range("F3") <> Prev_Val Then
Application.EnableEvents = False
Range("I3") = Range("F3") - Prev_Val
Prev_Val = Range("F3")
Application.EnableEvents = True
End If
End Sub
I've tried using:
If Target.Address = "$F$3" Then
'code here
But that does not seem to work.
Context: I'm using RTD with a stock simulator to automatically populate fields in Excel. Several calculations are done on the incoming data, but I cant do any of them without having Cell I3 work properly!
This might work, instead of the Worksheet_Change event, use the Worksheet_Calculate event. This procedure runs every time the sheet calculates, so you will need to have Automatic calculation enabled (this is normal default setting).
This is basically your exact code, slightly tweaked:
Public Prev_Val As Long
Private Sub Worksheet_Calculate()
Dim rngF3 As Range
Set rngF3 = Range("F3")
If rngF3 <> Prev_Val Then
Application.EnableEvents = False
Range("I3") = rngF3 - Prev_Val
Prev_Val = rngF3
Application.EnableEvents = True
End If
End Sub
Now one limit I think is that after you end the session, save/close the file, etc., the value of Prev_Val will not persist. There are a number of ways you might work around this limitation using a hidden worksheet to store the value, or a Name variable in the worksheet/workbook, or CustomDocumentProperties (I think I recently wrote an answer here to another Q about how to use CustomDocumentProperties, and I'm certain I have a few about using Names for this sort of approach, too...).
But maybe the simplest would be to do something like this in the Worksheet_Activate event
Private Sub Worksheet_Activate()
If Prev_Val = 0 Then Prev_Val = [F3]
End Sub
I haven't really tested that too thoroughly, though, and it may not be a perfect fit for you, so it might be better to use the CustomDocumentProperties, here is an example:
Alternatives to Public Variables in VBA
Several of the other possible methods are posted as answers in that Q, too.
Hope this helps!
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.