Time Delay in VBScript - vbscript

i want to introduce a 3 hour delay between two consecutive lines in my VB script code.
I am using the following code snippet for this:
WScript.Sleep 10800000
But I think the code is stopping for a long time, much more than 3 hours. I used 10800000 as i read time is given in milliseconds.
Please let me know my mistake and the correct way to achieve this.
Thank You!

Try something like this:
timeout = DateAdd("h", 3, Now)
Do Until Now > timeout
WScript.Sleep 200
Loop

Important This solution was provided because question was tagged excel-vba at the beginning.
I will give you different option. I imagine you have something like this at the moment:
Sub MyCurrentSub()
Dim A
A = 10
'wait 3 hour here and...
'...after 3 hours do other part of the sub
MsbBox A
End Sub
During waiting time, even if you use different option to wait (like Do...Loop) your Excel application will be limited, at least partially will not work as usually.
I would do it in this way, by creating and calling different Sub at the right moment:
Public A
Sub MyNewSub_1()
A = 10
Appication.OnTime Now + TimeValue("03:00:00"), "MyNewSub_2"
End Sub
'now you can use your Excel as usually...
Sub MyNewSub_2()
MsgBox A
End Sub
You will get the same result, Excell will be free for you to use for 3 hours during waiting time. The only think you need to remember is to- DO NOT QUIT APPLICATION. If you Quit Excel it will 'forget' to call MyNewSub_2.

Related

VBS & WSH error on simple loop and cpu over usage

I have a simple script that hunts for popup boxes that are generated for website and Excel.
It works most of the time but errors out occasionlly and seemingly randomly.
The error is
line: 6
Char: 3
Error: Invalid window handle
Code: 80070578
I can't figuer out why it'll work for hours then error seemingly at random.
Also the script uses a lot of CPU if anyone could advise how to make it more efficent.
Thanks For your time
Set WshShell = CreateObject("WScript.Shell")
Do
Do
ret = WshShell.AppActivate("Message from webpage")
ret2 = WshShell.AppActivate("Microsoft Excel")
Loop Until ret = True or ret2 = True
WScript.sleep 500
ret = WshShell.AppActivate("Message from webpage")
ret2 = WshShell.AppActivate("Microsoft Excel")
If ret = True or ret2 = True Then
WScript.Sleep 200
WshShell.SendKeys("{ENTER}")
End If
WScript.sleep 500
Loop
The simple answer is VBScript is not designed to run scripts continuously.
As for what you can do the improve it, let's dissect it a little.
The outer loop is running every 500 milliseconds, which means that every half a second the script is triggered forever this is heavy for what it is doing and will likely cause heavy CPU usage the longer it runs.
Does the outer loop need to run so often, could you not increase the Sleep() from 500 to say 1000 or even 5000 to reduce the load on the CPU?
Better yet you could drop the outer loop completely and run the task using Windows own Task Scheduler which will allow you to create a scheduled task that will execute the script however often you wish. That way the script runs to completion closes releases the memory and is then run again at the next interval.

Loop is taking around 10 minutes in vb

For Each drow As DataGridViewRow In DgvItemList.Rows
drow.Cells("strSrNo").Value = drow.Index + 1
Next
I have more than 3500 records in DgvItemList. I just give to numbering to that records but it tool 9 to 10 minutes for that.
How to reduce this time ?
Two things. Each time you change the value, it could cause the DataGridView to update, so just before your loop, add
DgvItemList.SuspendLayout
and after the loop, add
DgvItemList.ResumeLayout
You could also change the loop to a Parallel.For loop, so your final code would be something like
DgvItemList.SuspendLayout
Parallel.For(0, DgvItemList.Rows.Count, Sub(index As Integer)
DgvItemList.Rows(index).Cells("strSrNo").Value = DgvItemList.Rows(index).Index + 1
End Sub)
DgvItemList.ResumeLayout
Try it with just the Suspend and Resume layout first. You may not get a vast amount of improvement from the parallelization. Worth a go though.

Excel Power Query - Sleep or Wait Command to Wait on API Rate Limit

In Excel Power Query (PQ) 2016, is there such a function that can insert a "SLEEP 15 seconds" before proceeding? Not a pause, but a sleep function.
Problem:
I wrote a function in PQ to query: https://westus.api.cognitive.microsoft.com/text/analytics/v2.0. That function works fine, as designed.
I have a worksheet with 10K tweets that I want to pass to that function. When I do, it gets to ~60 or so complete and I get an ERROR line in PQ. A look at Fiddler says this:
message=Rate limit is exceeded. Try again in 11 seconds. statusCode=429
I think if I insert a SLEEP 5 second (equivalent) command into the PQ function, it won't do this.
Help & thanks.
You want Function.InvokeAfter
Function.InvokeAfter(function as function, delay as duration) as any
Here's an example:
= Function.InvokeAfter( () => 2 + 2, #duration(0,0,0,5))
Returns 4 after waiting 5 seconds.
To answer a question you didn't ask yet, if you're going to execute the exact same Web.Contents call a second time, you may need to use the
[IsRetry = true]
option of Web.Contents to indicate you actually want to run the web request again..

VBScript: Reminder for office workers and personal use

My program asks the user for any events that he will be having later on (eg. meeting/special lunch event/submit report/pay bills/birthday) and will remind the user when the time comes.
Here is my code:
Dim remind
re=MsgBox("Do you want me to remind you anything later on?", vbYesNo, "Reminder")
If re=6 then call main
Sub main
' Ask for the time that the user wanted to be reminded
remind=InputBox("At what time?" & vbNewLine &
"Please use this format {H:MM:SS AM/PM}" & vbNewLine &
"Note: H is in 12h format")
' Description eg. "Lunch with boss"
reminder=InputBox("Any discription you want to add in?")
Do Until check=remind
check=Time
If check=remind Then MsgBox reminder
Loop
End Sub
For example, I put in 12:30:00 PM and Lunch with boss. Even when the time comes nothing happens, no popup. And when I check my TaskManager it is still running.
I'm using wscript.exe to run this script. It's the do until check=remind part that doesn't work. If I put do until check="12:30:00 PM" then it will work.
PS: I know we can use the Microsoft Outlook for the reminder or even use our phones. But this is well suited for workers that are 24h infront of the computer and lazy to use their phones and update their outlook.
Convert to Date data type
The issue seems to be that the remind variable is a String data type, and the check variable is a Date data type. When you try to compare them, they'll always fail to be equal, even if the actual date inside both types is the same.
You can solve the problem by using the CDate function to convert remind to a Date before entering the loop.
remind = CDate(remind)
Validation
Because you're now using CDate to convert the user's input, if they make a typo and enter an invalid date, its going to bring up an error box and end the program. You may want to use IsDate to ensure it is a valid time before converting it, then gracefully ask the user to enter the time again if they made a typo.
CPU Usage
Your loop will sit there taking up 100% CPU usage of one core of the machine its running on. This can slow down your user's computer, among other side effects.
To fix this issue, you want to slow down the loop, such that its only checking a few times a second, rather than a few hundred times a second. Insert this statement inside the loop to have it sleep for 500 milliseconds before trying again.
WScript.Sleep 500

VB.NET Timer question

I wrote a VB.NET Windows Service, which works fine. I have only one issue with it. I want the service to execute on the half hour and top of the hour marks (e.g. 9:00, 9:30, 10:00, 10:30, 11:00, etc etc etc). I am using the following code:
Protected Overrides Sub OnStart(ByVal args() As String)
' Add code here to start your service. This method should set things
' in motion so your service can do its work.
Dim oCallBack As New TimerCallback(AddressOf TimedEvent)
oTimer = New System.Threading.Timer(oCallBack, Nothing, 300000, 300000)
EventLog.WriteEntry("CCFinalizeService has begun successfully." , _
System.Diagnostics.EventLogEntryType.Information)
End Sub
This code works, however, if the service starts at, say, 10:15, then it executes at 10:15, 10:45, 11:15, 11:45. How do I make it so it always executes on the 30 minute and top of the hour marks?
You could change it so that, at startup, it figures out the time required to go to a half hour increment based off the current time. Basically, your first timer would be <300000, then switch to every 300000.
Alternatively, you might want to consider using the Windows Task Scheduler instead of doing this as a service. The task scheduler lets you specify specific times to run an application.
You just need to modify the dueTime parameter in the Timer creation method
Dim now As Date = DateTime.Now
Dim dueTime As Integer ' milliseconds to the next half-hour
dueTime = 1800000 - (now.Minute Mod 30) * 60000 - now.Second * 1000 - now.Millisecond
oTimer = New System.Threading.Timer(oCallBack, Nothing, dueTime, 1800000)
Probably the easiest solution would be to test, at service startup, the current time, via the Date.Now property. You can then use a second timer to start the first timer, but set the Interval on the second timer to fire only at the next 1/2 hr or full hour mark.
Alternately, in your startup routine, have an infinite while loop that tests to see if the current time is on your mark. If not, System.Threading.Thread.Sleep(1000) and test again.
Good luck!
Maybe something like this??
If Now.Minute <> 0 Or Now.Minute <> 30 Then
Thread.Sleep((30 - Now.Minute) * 60 * 1000)
End If

Resources