Pause VBA code without pausing spreadsheet - vba

I have a VBA code where it is copying and pasting data from a spreadsheet that pulls data from an external server. Consequently, that spreadsheet takes awhile (from 10-30 seconds) to load the data.
I have researched how to pause a macro - application.wait, sleep, etc - but they also pause the spreadsheet functions so the data from the external server cannot load. Therefore when the code copies the data, it pastes #DIV/0!. Is there a function that can interrupt/stop/pause the macro to give the server data time to load?
I also would like this macro to run without needing user input (some suggestions online had the user advancing the code each iteration).
Sub all()
Dim wb1 As Workbook
Set wb1 = Workbooks("all")
Dim wb2 As Workbook
Set wb2 = Workbooks("other")
For i = 2 To 5
Application.Wait Now() + TimeValue("00:01:00")
wb2.Sheets("Sheet1").Cells(4, 2).Copy
wb1.Sheets("Sheet1").Cells(i, 18).PasteSpecial xlPasteValues
Next i
End Sub

Application.Wait suspends processing in Excel. This means that your background processing will suspend, too.
Instead, try this:
Dim WaitTime as Date
For i = 2 To 5
WaitTime = Now() + TimeValue("00:01:00")
While Now() < WaitTime
DoEvents
Wend
wb2.Sheets("Sheet1").Cells(4, 2).Copy
wb1.Sheets("Sheet1").Cells(i, 18).PasteSpecial xlPasteValues
Next i

Related

Getting vba to wait before proceeding

I need to update 4 different workbooks, which all collect data from bloomberg. I tried to construct a new workbook which will automatically open them and then the code within the workbooks will get activated since the code gets activated whenever the workbook opens. However my macro opens all workbooks at the same time and the update is taking too long when they are open at the same time. I tried to use the command "doevents" and "Application.Wait (Now + TimeValue("0:03:30"))", however they do not work. I would like them to open one at the time, then let the calculation in the specific workbook end before opening the next the next workbook.
Here is my code:
Sub UpdateWorkbooks()
'Quick Financial Longer Series
Workbooks.Open ("G:\FONDS\Quick financials_Longer Series.xlsb")
Application.Wait (Now + TimeValue("0:03:30"))
'Quick Financial
Workbooks.Open ("G:\FONDS\Quick Financial\Auto\Quick financials.xlsb")
Application.Wait (Now + TimeValue("0:03:30"))
'Quick Intra Corr (SX5E)
Workbooks.Open ("G:\FONDS\Quick Financial\Auto\Quick Intra Corr(SX5E).xlsb")
Application.Wait (Now + TimeValue("0:03:30"))
'SPX Sector Correlation
Workbooks.Open ("G:\FONDS\SPX Sector Correlation.xlsb")
Application.Wait (Now + TimeValue("0:03:30"))
Workbooks("UpdateWorkbooks.xlsb").Close savechanges:=True
End Sub
the application.calculationstate may help here. Wrap it up in a function, you could even return the state, and use a do until. Not sure of the infinite loop possibilities, so may be advisable to add a retry counter also.
Select Case Application.CalculationState
Case 0: strCalculationState = "Calculating"
Case 1: strCalculationState = "Done"
Case 2: strCalculationState = "Pending"
End Select

Only paste last piece of code in column

I am relatively new to this software and could really use a hand. I am using Ditta to store multiple items on a clipboard and have given them a shortcut. With this script I am trying to get it to paste all copied items at once, using a shortcut key. I have tested each block of code individually and it works. But when I try to run it together, it only runs the final block. Does anyone have any idea why this is happening?
Sub Data()
ActiveCell.Select
SendKeys "^4", True
Application.Wait (2000)
ActiveCell.Offset(0, 1).Range("A1").Select
SendKeys "^3", True
Application.Wait (1000)
ActiveCell.Offset(0, 1).Range("A1").Select
SendKeys "^2", True
Application.Wait (1000)
ActiveCell.Offset(0, 1).Range("A1").Select
SendKeys "^1", True
Application.Wait (1000)
End Sub
I don't know where exactly the issue is, but it seems that it is all about waiting for Ditto to insert the values. Your code is just not waiting until the paste is done.
I wrote a workaround for that:
We have a loop now that runs from 4 to 1 counting backwards (this is to send the 4 keys. This is easier than having 4 times the same code.
The main idea is to clear the cell before we paste, and after the paste we wait until the cell is not empty anymore, which means the paste was successful. Note this is just a workaround to wait an amount of time until the paste is done.
Option Explicit
Public Sub InsertData()
Dim i As Long
For i = 4 To 1 Step -1 'loop from 4 to 1 backwards
ActiveCell.Clear 'clear active cell (so we know it is empty for sure)
SendKeys "^" & CStr(i), True 'send keys for paste
'wait until active cell isn't empty anymore.
'this means wait until paste is done
Do While IsEmpty(ActiveCell)
DoEvents 'give Excel some time to handle other events
Loop
'move over to the next cell
ActiveCell.Offset(0, 1).Select
Next i
End Sub
Just a note to your original code
Your waiting was wrong anyway Application.Wait(2000) does not what you expect it to do. The correct way would be:
Application.Wait(Now + TimeValue("0:00:02"))
To make it wait 2 seconds. The given time is not the amount of time to wait but the absolute time until the macro waits. For more see Application.Wait Method.

VBA: To calculate the worksheet in background, while message userform is active

I wrote a loop procedure in vba, which pastes a lot of data each time to the new worksheet. Actually it pastes the formulas that get calculated. It takes excel approximately 40 seconds to get all calculations done. Unfortunately the next loop does not wait 40 seconds and fills with the data the next sheet. It takes a lot of resources. To make a loop to wait a little bit, but still to perform calculations I used userform, which appears for 40 seconds, than it will be unloaded and is used in the next loop. The purpose of the userform is to allow the calculations to get done before the calculations in the next sheet begin. This strategy has a drawback, since when the useform is active, the calculations in the background freeze. One can change the options of the useform to showmodal false, but then I cannot upload and unload it each time as new loop begins. Besides I am not sure weather the formulas a still calculated in the inactive sheet. I have to mention that the formulas in the sheet each time activate an excel add-in and I cannot make an add in to wait with calculations, even if the option manual calculations is turned on.
If anybody knows how to postpone the loop but not to make complete excel application wait (Application.wait or ontime methods do not work) I will appreciate the help a lot. I tried also to active and deactivate events, switch to manual calculation and back. Also this does not help and all data a calculated at once.
The method described in the other post did not worked for me and all formulas are still calculated at the same time:
Application.Calculate
If Not Application.CalculationState = xlDone Then
DoEvents
End If
My original code that copies formulas to the new worksheet:
For raw_i = 1 To 3
Set o = GetObject("d:\formulas.xlsx")
Set Sheet_i = Worksheets.Add(after:=Worksheets(Worksheets.Count))
Sheet_i.Cells(1, 1).Formula = o.Worksheets("Sheet1").Cells(raw_i, 1).Formula
Set o = Nothing
LoadForm
next raw_i
VBA doesn't support multiple process threads - there is one execution route and if you pause it, then you pause the whole execution. It's all or nothing.
Best hope you've got is a While Loop:
While Application.CalculationState <> xlDone
DoEvents
Wend
Which will loop until calculations have finished.
In response to your most recent edit:
Try changing the main loop to:
For raw_i = 1 To 3
Set o = GetObject("d:\formulas.xlsx")
Set Sheet_i = Worksheets.Add(after:=Worksheets(Worksheets.Count))
Sheet_i.Cells(1, 1).Formula = o.Worksheets("Sheet1").Cells(raw_i, 1).Formula
Sheet_i.Calculate
DoEvents
Set o = Nothing
Next

Macro to start at a particular time

I have found sources that say to use
Application.OnTime TimeValue("18:00:00"), "MyMacro"
But I can't seem to get it to work. This is what I have entered
Sub TimeStamp()
'
' TimeStamp Macro
'
' Keyboard Shortcut: Ctrl+Shift+T
'
Application.OnTime TimeValue("13:25:00"), "TimeStamp"
' Following refreshes the data
Application.CalculateFullRebuild
Then the rest of the code followed by End Sub
For whatever unknown reason, when I start the Macro, it does not wait until that given time. What syntax rules am I breaking here?
The macro is triggered when the macro is triggered. OnTime schedules it to be run automatically, but why should that prevent you from running it manually? Think of it like a virus scan. Many people have their computers configured to do automatic scans at certain set times, but are perfectly able to run nonscheduled scans at any time. If you want to make sure that your macro doesn't have any effect before a certain time, use an if - then statement involving Now (if it is too early exit sub) -- although it makes more sense to not run it at all when you don't want to.
Another method that I've used for years successfully is by just creating a small vb script that is scheduled to call the macro. My other answer to a very similar question show this example script
Dim xlApp
Dim xlWkb
Set xlApp = CreateObject("excel.application")
Set xlWkb = xlApp.Workbooks.Open("PATH TO YOUR FILE")
xlApp.Visible = True
xlWkb.RunAutoMacros 1 'enables macros to be run on open
xlApp.Run ("YOUR PROCEDURE")
xlApp.Workbooks("YOUR WORKBOOK NAME").Save 'Save the workbook
xlApp.Quit 'quits excel
Schedule this through Tasks Scheduler. My other answer can be found here
This is what I ended up with thanks to the help of several of you. I used:
Private Sub Workbook_Open()
Application.Wait "6:45:00"
Call TimeStamp
End Sub
and placed this in "ThisWorkbook". This made it so that when I open up my workbook, the macro is automatically started but it waits until 3:03 pm to perform the rest of the task.
Next, I needed it to refresh every 15 minutes so I used Chip's solution suggested by User: Findwindow. The code goes as follows
Public RunWhen As Double
Public Const cRunIntervalSeconds = 900 ' 15 minutes
Public Const cRunWhat = "TimeStamp" ' the name of the procedure to run
Sub StartTimer()
If Time < TimeSerial(13, 15, 0) Then
RunWhen = Now + TimeSerial(0, 0, cRunIntervalSeconds)
Application.OnTime EarliestTime:=RunWhen, Procedure:=cRunWhat, _
Schedule:=True
End If
End Sub
at the end of the TimeStamp macro, I put Call StartTimer so that every time the macro is ran, the timer will schedule a new run time for 15 minutes from the current time. The If Time < TimeSerial(13, 15, 0) Then allows for the macro to stop running at 1:15pm, the time that I wanted it to stop.

Vb excel loop not updating

I have the following code and what I try to do is basically collect data and locate that data in a cell starting from A1 up to A100 the data comes from cell M4 this particular cell is dynamic and is constantly changing it's value, is Pulling data from DDE
the code works but for some reason it takes the first value and does not update as the M4 is changing.
Any Ideas?
Sub looptest()
Dim loop_ctr As Integer
For loop_ctr = 1 To 100
ActiveSheet.Range("A" & loop_ctr).Value = Worksheets("sheet1").Range("M4")
Application.Wait (Now + TimeValue("0:00:01"))
Next loop_ctr
MsgBox " Done! "
End Sub
After Application.Wait ... line try adding:
DoEvents
As written, you code doesn't expose Excel to any other system events, like your DDE, to update the Excel application for the entire 100 second execution time of your loop.