VBA function to alert when value is changed within a time frame - vba

I have an excel cell where its value is updated every minute.
What I need is an alert message box; while that cell value moves to a particular time.
Suppose a cell has value 10:
if it reaches 7 in one minute then I need a message box to alert that.
if it is not reaching 7 in one minute then I don't need any alert.
Please help write me a macro for this.

Inside VBA editor for ThisWorkBook, you could write the following code
Dim WithEvents SheetToWatch As Worksheet
Private Sub SheetToWatch_Change(ByVal Target As Range)
If Target.Address = "$A$2" Then
If Target.Value = 7 Then
MsgBox "changed to 7"
End If
End If
End Sub
Private Sub Workbook_Open()
Set SheetToWatch = Sheets("Sheet1")
End Sub
Basically the code sets the reference of Sheet1 to the variable SheetToWatch when the workbook opens. Declaring the variable using WithEvents lets one capture the events.
I am using Change event of the worksheet and checking if the cell that was changed is A2. If so, I am checking or comparing the value with 7 (it can be dynamic and depends on how you want to handle it).
See if this helps.

Cannot be done with a function, any way that I can think of.
If you control the mechanism that is updating the cell, then you could it call a VBA subroutine that you wrote, instead, have to send the alert and then update the cell from that routine.
If you do not control the updating mechanism, then the only thing that I can think of that might work is of the Cell, Range or Worksheet classes have a ChangedDate event that you could catch from VBA and do your alerting from there.

Related

How to trigger VBA Workbook_SheetCalculate Event?

I tried Workbook_SheetCalculate Event and tried to trigger it, but it did not work, although I recalculated the worksheet!
How to trigger this Event?
here is an example, in the worksheet for the event have the following code:
Private Sub Worksheet_Calculate()
MsgBox "Calculating"
End Sub
Then in the sheet, in any cell, enter =RAND()
The formula causes a recalculation and triggers the event.
Or from a standard module use the following:
Public Sub Test()
'Application.Calculate ''could use this event for the workbook
With Worksheets("Sheet5") 'sheet containing the event code
.Calculate
End With
End Sub
The key seems to be that there is something in the sheet to calculate e.g. =RAND().
I remembered from another post, at some point, a link to the following Excel’s Smart Recalculation Engine
A quick extract says:
Excel normally only calculates the minimum number of cells possible.
Excel’s smart recalculation engine normally minimises calculation
time by tracking changes and only recalculating
Cells, formulae, values or names that have changed or are flagged as needing recalculation.
Cells dependent on other cells, formulae, names or values that need recalculation.
So, if you just had constants in the sheet, even if you issue a Worksheet.Calculate the msgbox wouldn't appear. You could test this by removing the =RAND() from the sheet and just putting 1 in the cell.
If I have two sheets each with a single non-volatile formula, and this in the workbook module:
Private Sub Workbook_SheetCalculate(ByVal Sh As Object)
Debug.Print Sh.Name
End Sub
I see both sheets names on calling:
Application.CalculateFull
or:
Application.CalculateFullRebuild
but no output with:
Application.Calculate
If I add a volatile formula to one of the sheets then I get that sheet when calling Application.Calculate.
If you're still having problems then you'd need to post a few more details including your event code and what types of formulas you have on your sheets.

Run macro when linked cell changes value (Excel VBA)

I am currently trying to obtain historical information about how the backlog is developing.
My Excel file is based on queries from an Access Database which can give me a view of the current situation.
I would like to automatically run a macro every time the week number changes. I am currently using the following code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Target.Worksheet.Range("D3")) Is Nothing Then
Call KPIupdate
End If
End Sub
The macro that should fire is called KPIupdate
My problem is that the Macro only fires if I click the cell. I would like it to just fire when the number changes. The cell "D3" is linked to another cell with the formula =Weeknum(Today();21)
I hope you can help me
According to the MSDN entry for Worksheet_Change:
This event does not occur when cells change during a recalculation. Use the Calculate event to trap a sheet recalculation.
To use Worksheet_Calculate to trap the change in a cell that is set by a formula looking at another cell, you need to set a variable to hold the value of the 'Target' and then check if it has changed after the Calculate event fires.
Here is a simple example:
Option Explicit
Private strCurrentWeek As String
Private Sub Worksheet_Calculate()
If Me.Range("A1").Value <> strCurrentWeek Then
'the linked cell changed
Debug.Print "Sheet1!A1 was changed"
'call another macro
End If
'update the new current week
strCurrentWeek = Me.Range("A1").Value
End Sub
To test this, just set the formula in A1 to be =B1 and then change the value of B1 and check the output in the Immediate window.
You can adapt this code to call KPIupdate where my Debug.Print... statement is.

Need to run a VBA Macro on data refresh in excel

I am attempting to prompt a macro to run on a data refresh. I have the macro that needs to be run build, but I am having an issue with the new values not being used since the macros embedded in the sheet are called using ActiveX ComboBoxs.
I am finding several instances where people refer to AfterRefresh and BeforeRefresh, but I think I am misunderstanding how this would take effect and call a macro.
I currently am running ComboBoxs so I have multiple instances of
Private Sub ComboBox22_Change()
'do stuff
End Sub.
but I need the 'do stuff' to occur upon a data refresh, including refreshes that happen automatically and upon sheet open.
I don't want to tie the refresh to a specific box because the items that are refreshed are not dependent on any one instance of data change.
Any help is greatly appreciated.
Thank you.
Maybe a worksheet change event would help in this situation.
Right Click the sheet tab, select "View Code", Select "Worksheet" then "Change."
Code will automatically kick in when a specific range of cells has been changed.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Count > 1 Then Exit Sub ' this stops code error if more than one cell is changed at once
If Not Application.Intersect(Target, Me.Range("A1:C10")) Is Nothing Then ' indicates the Target range
MsgBox "You have changed " & Target.Address & " to " & Target
End If
End Sub
You could also use Worksheet_pivottableupdate event to run the macro. You set it up in a similar way to davesexcel answer above.
The connection in question may not be a pivot table but you can use a small and fast pivot table as a trigger.
Set the pivot table to update at the same time as your connection (e.g. set to self refresh every 5 minutes or on workbook open).

Set the value of a cell when unsaved changes are detected in Excel using VBA

I'm trying to detect changes within an entire workbook (doesn't matter what changes) so that any change that occurs prior to save will result a specific cell getting set to a specific value. The goal is to show a visual indicator of whether the workbook is saved using conditional formatting (non issue, already have that set up).
The code I use to set the value of the cell is Sheets("Sheet1").Range("H1").Value = 1.
I've tried to detect changes by using Sub Worksheet_Change(ByVal Target As Range), but I'm unsure of how to set the range.
Any help would be greatly appreciated.
If I'm reading your question correctly, you want to setup your worksheet so that every time a change is made by a user, update the value in the cell.
You are already most of the way there, you just need to put the following subroutine in your workbook.
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
Sheets("Sheet1").Range("H1").Value = 1
End Sub
Once this is saved with your workbook, that specific workbook will perform the functionality you require. Here's a link to the documentation - http://msdn.microsoft.com/en-us/library/office/ff839775(v=office.15).aspx.
Private Sub Worksheet_Change(ByVal Target As Excel.Range) 'Target is the variable name of the Range where the Change occured
If thisworkbook.saved=false then
Sheets("Sheet1").Range("H1").Value = 1
else
Sheets("Sheet1").Range("H1").Value = 0 'or other value
End if
End Sub

OnClick in Excel VBA

Is there a way to catch a click on a cell in VBA with Excel? I am not referring to the Worksheet_SelectionChange event, as that will not trigger multiple times if the cell is clicked multiple times. BeforeDoubleClick does not solve my problem either, as I do not want to require the user to double click that frequently.
My current solution does work with the SelectionChange event, but it appears to require the use of global variables and other suboptimal coding practices. It also seems prone to error.
Clearly, there is no perfect answer. However, if you want to allow the user to
select certain cells
allow them to change those cells,
and
trap each click,even repeated clicks
on the same cell,
then the easiest way seems to be to move the focus off the selected cell, so that clicking it will trigger a Select event.
One option is to move the focus as I suggested above, but this prevents cell editing. Another option is to extend the selection by one cell (left/right/up/down),because this permits editing of the original cell, but will trigger a Select event if that cell is clicked again on its own.
If you only wanted to trap selection of a single column of cells, you could insert a hidden column to the right, extend the selection to include the hidden cell to the right when the user clicked,and this gives you an editable cell which can be trapped every time it is clicked. The code is as follows
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'prevent Select event triggering again when we extend the selection below
Application.EnableEvents = False
Target.Resize(1, 2).Select
Application.EnableEvents = True
End Sub
In order to trap repeated clicks on the same cell, you need to move the focus to a different cell, so that each time you click, you are in fact moving the selection.
The code below will select the top left cell visible on the screen, when you click on any cell. Obviously, it has the flaw that it won't trap a click on the top left cell, but that can be managed (eg by selecting the top right cell if the activecell is the top left).
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'put your code here to process the selection, then..
ActiveWindow.VisibleRange.Cells(1, 1).Select
End Sub
SelectionChange is the event built into the Excel Object model for this. It should do exactly as you want, firing any time the user clicks anywhere...
I'm not sure that I understand your objections to global variables here, you would only need 1 if you use the Application.SelectionChange event. However, you wouldn't need any if you utilize the Workbook class code behind (to trap the Workbook.SelectionChange event) or the Worksheet class code behind (to trap the Worksheet.SelectionChange) event. (Unless your issue is the "global variable reset" problem in VBA, for which there is only one solution: error handling everywhere. Do not allow any unhandled errors, instead log them and/or "soft-report" an error as a message box to the user.)
You might also need to trap the Worksheet.Activate() and Worksheet.Deactivate() events (or the equivalent in the Workbook class) and/or the Workbook.Activate and Workbook.Deactivate() events so that you know when the user has switched worksheets and/or workbooks. The Window activate and deactivate events should make this approach complete. They could all call the same exact procedure, however, they all denote the same thing: the user changed the "focus", if you will.
If you don't like VBA, btw, you can do the same using VB.NET or C#.
[Edit: Dbb makes a very good point about the SelectionChange event not picking up a click when the user clicks within the currently selected cell. If you need to pick that up, then you would need to use subclassing.]
I don't think so. But you can create a shape object ( or wordart or something similiar ) hook Click event and place the object to position of the specified cell.
This has worked for me.....
Private Sub Worksheet_Change(ByVal Target As Range)
If Mid(Target.Address, 3, 1) = "$" And Mid(Target.Address, 2, 1) < "E" Then
' The logic in the if condition will filter for a specific cell or block of cells
Application.ScreenUpdating = False
'MsgBox "You just changed " & Target.Address
'all conditions are true .... DO THE FUNCTION NEEDED
Application.ScreenUpdating = True
End If
' if clicked cell is not in the range then do nothing (if condttion is not run)
End Sub
NOTE: this function in actual use recalculated a pivot table if a user added a item in a data range of A4 to D500. The there were protected and unprotected sections in the sheet so the actual check for the click is if the column is less that "E" The logic can get as complex as you want to include or exclude any number of areas
block1 = row > 3 and row < 5 and column column >"b" and < "d"
block2 = row > 7 and row < 12 and column column >"b" and < "d"
block3 = row > 10 and row < 15 and column column >"e" and < "g"
If block1 or block2 or block 3 then
do function .....
end if
I had a similar issue, and I fixed by running the macro "onTime", and by using some global variables to only run once the user has stopped clicking.
Public macroIsOnQueue As Boolean
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
macroIsOnQueue = False
Application.OnTime (Now() + TimeValue("00:00:02")), "addBordersOnRow"
macroIsOnQueue = True
End sub
Sub addBordersOnRow()
If macroIsOnQueue Then
macroIsOnQueue = False
' add code here
End if
End sub
This way, whenever the user changes selection within 2 seconds, the macroIsOnQueue variable is set to false, but the last time selection is changed, macroIsOnQueue is set to true, and the macro will run.
Hope this helps,
Have fun with VBA !!
Just a follow-up to dbb's accepted answer: Rather than adding the immediate cell on the right to the selection, why not select a cell way off the working range (i.e. a dummy cell that you know the user will never need). In the following code cell ZZ1 is the dummy cell
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Application.EnableEvents = False
Union(Target, Me.Range("ZZ1")).Select
Application.EnableEvents = True
' Respond to click/selection-change here
End Sub