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
Related
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.
I have a workbook that crashes Excel on close when the close is triggered by an API timer.
Edit: The workbook in link below has nothing but the timer and exit modules and it has the same behavior so it's not an issue with the content.
https://www.dropbox.com/s/x0xdwgj5h34ctdk/Book1.xlsm?dl=0
A few seconds after the workbook closes Excel crashes. I have tried turning the timer off, unhiding all sheets, unloading forms...all the objects are set to Nothing.
All I am doing is Workbooks(ThisWorkbook.Name).Close SaveChanges:=True??!!
The same sub is called from a UserForm with no problem. The workbook closes without Excel crashing.
How to fix this?
Sub ApplicationExit()
' Call UnloadAllForms
' DoEvents
' Sleep 1000
' Call StopCloseTimer
'DoEvents
'If Application.Workbooks.Count = 1 Then
' Workbooks(ThisWorkbook.Name).Save
' Application.Quit
'Else
DoEvents
Workbooks(ThisWorkbook.Name).Close SaveChanges:=True
'End If
End Sub
The code triggered by the timer is;
Sub TimerCalled()
If CloseTimerValue = "" Then Call Reset_CloseTimerValue
DoEvents
If basTimers.CloseTimerValue <= Now() And Not Unlocked Then Call ApplicationExit
On Error Resume Next 'In case sheet is protected
ThisWorkbook.Sheets("JobIndex").Range("CloseCount").Value = Format(Now() - CloseTimerValue, "hh:m:s")
End Sub
The userform says;
CloseUp:
i = MsgBox("Close Project Register?", vbYesNo, MsgBoxTitle)
Select Case i
Case vbYes
Call ApplicationExit
Case vbNo
Workbooks(ThisWorkbook.Name).Save
End Select
Timer in excel vba is done by using the Application.OnTime command or windows timer, as you are using.
Notice that, to schedule the call for a function (using the upper-mentioned command), it's used APPLICATION, which means it tells EXCEL to execute the call, not your workbook. So, in your case, the workbook is closed, BUT the to-be-called procedure is still scheduled to go off at some time in the future. The error that you get is that the excel doesn't find the procedure and then throws an error.
The reason it crashes in your case is that you are using windows timer to do it. When you close your workbook, your instance of the lib32 is lost and when time comes, Windows can't reach in the memory and then crashes the whole application.
In both cases, it seems that your scheduled procedure is still running.
I suggest that you look into that and consider using application.ontime.
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
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.
I have written a program to print multiple .pdfs with varying file extensions off of an Excel spreadsheet list.
The problem is that it takes anywhere from 30 seconds to a minute for the printer to receive the pdf after the line: Application.SendKeys "^p~", False is called.
To get by this I used Application.Wait (Now + TimeValue("0:01:03")) to wait for a minute (plus 3 seconds just to be safe) before closing the file.
To me there seems like there should be a better way than just causing the program to wait, so I looked around a little and found a question about this lovely gem known as Application.OnTime.
I tried a sample of one of the answers:
Sub test2()
ActiveSheet.Cells(1, 1).Value = ActiveSheet.Cells(1, 1).Value + 1
Application.OnTime Now + TimeValue("00:00:5"), "test2"
End Sub
However when I tried to stop the above code it kept going on an infinite loop and I was unable to stop it until I killed excel using the windows task manager.
I would like to be able to add in a little message box or something of the sort so that the user can click in between the wait time.
So that while the program is waiting for a minute, the user can either manually click and start the program on the next pdf, or click another button to exit if they need to stop printing early. Something like this:
Sub pdfPrinter()
'...
'Insert all the other code here
'...
Application.SendKeys "^p~", False
Application.OnTime Now + TimeValue("00:01:02"), "pdfPrinter"
continue= MsgBox("Click Retry to print again, or cancel to stop printer.", vbRetryCancel)
If continue = vbRetry Then
Call pdfPrinter
ElseIf continue = vbCancel Then
Exit Sub
End If
End Sub
Application.OnTime(unlike Application.Wait) is Asynchronous
so code after
Application.OnTime Now + TimeValue("00:01:02"), "pdfPrinter"
Runs Immediately.
If you want to print another PDF you need to call Application.OnTime with a different schedule of the 1st one.
Now, canceling Application.OnTime, when it is already started is a different story:
To do that you need to store that time that the respective function is scheduled to run and then Cancel it using the following code:
Application.OnTime Now + TimeValue("00:00:50"), "test", schedule:=False