Application.OnTime doesn't wait - excel

I have some graphs that are updated based on the value in one cell. I am trying to write a script that changes the value in this cell every second and updates the graphs in the process. However, the program does not seem to wait one second to call the procedure and rather runs everything directly. I have tried other methods such as Application.wait which works in regards to waiting but it does not update the graphs. From information I have found on the internet, it seems like Application.OnTime is the best option. Could someone help me figure out why Application.OnTime does not wait one second? Here is my code:
Sub graphOverTime()
Do While Range("N5").Value = "Running"
'changes cell N5 to Not running on condition
Call my_procedure
'Update value in D3 that impacts the graphs
current_month = Range("D3").Value
Range("D3").Value =
Application.WorksheetFunction.EoMonth(current_month, 1)
DoEvents
'Wait one second to rerun procedure
Application.OnTime Now + TimeValue("0:00:01"), "graphOverTime"
Loop
End Sub

Your main problem is Do While looping which causes Application.OnTime to set overlapping scheduled calls of graphOverTime. Following is one way of doing what you wanted to in the first place
Sub graphOverTime()
If Range("N5").Value = "Running" Then
'changes cell N5 to Not running on condition
Call my_procedure
'Update value in D3 that impacts the graphs
Range("D3").Value = Application.WorksheetFunction.EoMonth(Range("D3").Value, 1)
DoEvents
'Wait one second to rerun procedure
Application.OnTime Now + TimeValue("0:00:01"), "graphOverTime", False
End If
End Sub

Related

VBA - Trying to refresh data every second and also store that value in a new cell every refresh

I am trying all sorts of ways to refresh my random integers in B4:B419 and at the same time store the output of F1 in a new cell at the end of column F. Running RunAll only refreshes the data in B4:B419 and does not continuously paste the new values of F1.
Sub Calculate_Range()
Sheets("Shoe Simulation").Range("B4:B419").Calculate
Dim last_row As Long
last_row = Sheets("EV").Cells(Rows.Count, "F").End(xlUp).Row
Sheets("EV").Range("F1").Copy
Sheets("EV").Cells(last_row + 1, "F").PasteSpecial Paste:=xlPasteValues
End Sub
Sub Timeing()
Application.OnTime DateAdd("s", 1, Now), "Calculate_Range"
End Sub
Sub RunAll()
Call Calculate_Range
Call Timeing
End Sub
I don't have enough rep to comment, but are you trying to have the code run continuously non stop?
The reason why it isn't running continuously is because the RunAll sub only calls each function once.
It calls calculate_Range, which runs once and then it calls Timeing() which also has Calculate_Range run once.
If you add Call Timeing() to the end of your Calculate_Range sub, then it will loop between the 2 continuously. Please note though that this will effectively make an infinite loop.

While loop or On Time function when running script with a set time interval

I am have an Excel sheet that pushes in values every second. I would like to capture that and log it on a separate sheet every 5 seconds.
I am currently torn between using a Do While loop and the OnTime method. I was wondering what will be the pros and cons with using either methods. Or if there is a better way of periodically executing scripts, I am all ears as well.
Do While method:
Sub mainSub()
'On/Off
Do While Sheets("Main").Range("B3") = 1
'script to transfer prices
Application.Wait Now + #12:00:01 AM#
Loop
End Sub
On Time method:
Sub mainSub()
'On/Off
If Sheets("Main").Range("B3") = 1 Then
Call capturePriceSub
End If
End Sub
Sub capturePriceSub()
'script to transfer prices
Application.OnTime Now() + TimeValue("00:00:05"), mainSub
End Sub

Problem with building count down timer in Excel using VBA

I was trying to build a count down timer using VBA, and the result can be dynamically output to an Excel cell. I let procedure abc and def recursively call each other (did not set a stop point just for testing), and it worked. However, later with this exact same code I ran again, it failed, and error message was:
Code execution has been interrupted.
Just can't figure out why, I didn't change anything, how could it work and then fail?
I tried On Error Resume Next and Application.DisplayAlert = False, both don't stop the error message popping up and the interruption of the code execution. And if I step through the procedures, it seems fine...
Also I wish to add a dynamic text like "start in how many seconds" like in the comment in another cell. Can it be realized in this way?
Thank you!
Sub abc()
[a1] = [a1] - 1
' [a2] = "Start in " & [a1] & " seconds."
Call def
End Sub
Sub def()
Application.Wait (Now + TimeValue("0:00:01"))
Call abc
End Sub
Rather than trying to do this recursively, with concerns about the call stack, I would use Application.OnTime.
Sub Button1_Click()
Call MyTimer
End Sub
Sub MyTimer()
[a1] = [a1] - 1
Application.OnTime Now + TimeValue("00:00:01"), "MyTimer"
End Sub
I suppose this is still 'recursive' in a fashion, but the procedure exits each time. Only after 1 second has elapsed does it execute the procedure again.
But, either way, you should include some means of stopping the process. For example,
Sub MyTimer()
[a1] = [a1] - 1
If [a1] > 0 Then
Application.OnTime Now + TimeValue("00:00:01"), "MyTimer"
End If
End Sub
Your entire code is working fine for me (also including the [a2] part). I'm on Windows 7 with Excel 2013.
I suggest you include a stopping condition to abc() like
If [a1] > 0 Then
Call def
End If
Please provide some more information.
Why not create a function btw? Does it work for you?
Function wait(seconds As Long)
Dim originalStatusBar As String, i As Long
originalStatusBar = Application.StatusBar
For i = seconds To 0 Step -1
Application.wait (Now + TimeValue("0:00:01"))
Application.StatusBar = "Start in " & i & " seconds"
Next
Application.StatusBar = originalStatusBar
End Function
Then in your sub you just call it like so:
wait 5 'waits 5 seconds and updates status bar with remaining time
or
wait [a1]-1

VBA to refresh Bloomberg data not running in proper order

my purpose is to update Bloomberg data and do some calculatations with different tickers. But it seems that VBA will run all the calculations without waiting the data to be updated.
Here is the code:
Application.Calculation = xlCalculationAutomatic
For i = 1 To 3
Call Worksheets("Sheet1").Range("data1").Select 'the cells "data1" contains the function =BDH(ticker, field, start date, end date) to get the information from Bloomberg'
Call Application.Run("RefreshCurrentSelection")
Worksheets("sheet1").Range("d3").Value = Worksheets("sheet1").Range("sum") 'the cells "sum" takes the sum of all BB info'
Anyone know how to fix it?
Bloomberg formulae update is asynchronous so your code won't wait until the update is over. You need to schedule the rest of your code to a later time, check if the data has been updated.
It would look like this:
Application.Run "RefreshCurrentSelection"
update
Sub update()
If (check if the links have been updated) Then
Worksheets("sheet1").Range("d3").Value = Worksheets("sheet1").Range("sum")
Else
Application.OnTime earliestTime:= Date + Time + timeserial(0, 0, 1), _
procedure:="update", Schedule:=True
End if
End Sub
That would ask the Bloomberg API to refresh the data, then wait 1 second, check if the data is updated, wait another second if not etc. until the data is updated and then it would run the range assignment.
You have to split it up between a check and a refresh.
Sub RefreshData()
Application.Calculation = xlCalculationAutomatic
Worksheets("Sheet1").Range("A1:A4").Select 'the cells "data1" contains the function =BDH(ticker, field, start date, end date) to get the information from Bloomberg'
Application.Run "RefreshCurrentSelection"
'Check to see if it filled
Call Check_API
End Sub
Sub Check_API()
If Application.WorksheetFunction.CountIfs(Range("A1:A4"), "#N/A Requesting Data...") > 0 Then
'Check every 3 seconds
Application.OnTime Now + TimeValue("00:00:03"), "Check_API"
Else
'What to do after API filled
Worksheets("sheet1").Range("D3").Value = Application.WorksheetFunction.Sum(Worksheets("Sheet1").Range("A1:A4")) 'the cells "sum" takes the sum of all BB info'
End If
End Sub
Also, instead of focusing on the selection, you can do:
Refresh based on default option setting:
Application.Run "RefreshData"
Refresh current selection:
Application.Run "RefreshCurrentSelection"
Refresh current worksheet:
Application.Run "RefreshEntireWorksheet"
Refresh current workbook:
Application.Run "RefreshEntireWorkbook"
Refresh all workbooks:
Application.Run "RefreshAllWorkbooks"
If you were interested. Still the better option is implementing the v3 COM API class that can be found in Bloomberg's SDK with VBA examples.
Even though your Calls seems odd, you should be able to make use of the value from Application.CalculationState.
There are other ways to "pause" Excel, but you can do a simple While loop that do nothing except waiting for value of Application.CalculationState becomes xlDone.
Do Until Application.CalculationState=xlDone
Loop

How to refresh Excel file every second?

I have a list of stock prices pulled from Google finance and placed in different sheets in my Excel. I'm wondering, Can I refresh Excel sheet every SECOND (not minute) according to the Google finance stock price?
This can be done without having a macro constantly running. It relies on the Application.OnTime method which allows an action to be scheduled out in the future. I have used this approach to force Excel to refresh data from external sources.
The code below is based nearly exclusively on the code at this link: http://www.cpearson.com/excel/ontime.aspx
The reference for Application.OnTime is at: https://msdn.microsoft.com/en-us/library/office/ff196165.aspx
Dim RunWhen As Date
Sub StartTimer()
Dim secondsBetween As Integer
secondsBetween = 1
RunWhen = Now + TimeSerial(0, 0, secondsBetween)
Application.OnTime EarliestTime:=RunWhen, Procedure:="CodeToRun", Schedule:=True
End Sub
Sub StopTimer()
On Error Resume Next
Application.OnTime EarliestTime:=RunWhen, Procedure:="CodeToRun", Schedule:=False
End Sub
Sub EntryPoint()
'you can add other code here to determine when to start
StartTimer
End Sub
Sub CodeToRun()
'this is the "action" part
[A1] = WorksheetFunction.RandBetween(0, 100)
'be sure to call the start again if you want it to repeat
StartTimer
End Sub
In this code, the StartTimer and StopTimer calls are used to manage the Timers. The EntryPoint code gets things started and CodeToRun includes the actual code to run. Note that to make it repeat, you call StartTimer within CodeToRun. This allows it to loop. You can stop the loop by calling the StopTimer or simply not calling StartTimer again. This can be done with some logic in CodeToRun.
I am simply putting a random number in A1 so that you can see it update.
Sub RefreshFormulasEverySecond()
Dim dtTargetTime As Date
Debug.Print "Started"
Do While Range("A1").Value <> "STOP"
Application.Calculate
dtTargetTime = Now + TimeValue("0:00:01")
Do While Now < dtTargetTime
DoEvents
Loop
Debug.Print Now
Loop
Debug.Print "Stopped"
End Sub
You could have this macro running in the background. Paste it into a VBA module. You can run it from there or else put a button on the sheet and use that to trigger it. It's written to stop running when the word "STOP" is typed in cell A1 of whatever sheet the user is looking at.
I'm not sure it's the greatest idea to have a macro running continuously in the background, but that was the only way I could think of.

Resources