vba switch process based on time [duplicate] - vba

This question already has answers here:
Multi-threading in VBA
(8 answers)
Closed 6 years ago.
How can you switch between processes based on time?
++++
I have an Excel macro sending XML requests to Google, it has 3 important processes.
The process sending the XML requests. This process is limited to 10 requests per second.
A loading bar with the ability to quit the program
The Excel Application itself (it should be editable while the program is running)
The macro is currently using the sleep function (from kernel32.dll) to delay the processes, and the DoEvents function to make sure both process are run (and so the application can be modified in the background).
Ex. Process 1
Do While True
Call doSomething
DoEvents 'handles processes 2 and 3
Sleep 100
Loop
This method delays the entire application. Editing the Excel Worksheet in the background is laggy because of the 100ms delay, and attempting to quit the program is also delayed.
To remove this lag, I would like processes 2 and 3 to be running and switch control to process 1 when it is time to send a request. After the request is sent, process 1 can give control of the program back to processes 2 and 3. Does anyone have a solution to this?
Bonus: VBA seems to have little capability for multi threading/processing, but if anyone can think of a way to run all these processes at once I'd love to know about it

The implementation details are quite involved for each of the things you are looking for but they can be easily found by searching. So I'll suggest an approach for each of your questions.
Use Application.OnTime to trigger a macro to run after a given time interval.
Multiple threads can be executed, but it's tricky. You'll need to either
Invoke another instance of Excel and make it run your Macro, that way your main thread is not affected or
Put your macro into a separate text file (vb-script file) and call get it executed via Shell. That way you can continue executing the existing Macro and the user regains control of the UI, but the script fetches new data in the background.
Execute part of your code in a separate instance of Excel and then pump in the results into your current spreadsheet via DDE (older but fairly reliable technology) or by building something called an RTD server.
Ample examples of each of the above points are available on this site and elsewhere through Google.

Related

Continuous Loop/Repeat causes Excel to Crash (after hours/days)

I have some VBA code that runs every 15 minutes continually. This code runs fine at first but after a period of time (which varies from around 4 hours to 5 days) Excel crashes.
It is not a VBA crash (with debug option) but it is Excel freezing and saying the application needs to be restarted.
Am I trying to use Excel in a way it was not designed for? Should I be clearing some memory/cache to avoid this?
I believe it is due to a fail of the OnTime method of the application, I had your same problem some time ago with an Excel tool which was scraping data from the web every 5 minutes. Sometimes it just crashed with no specific log or error/warning. Here is the workaround I have implemented:
1) In the Workbook_Open event I have put :
myMacro 'the call to my procedure when the workbook is opened
ThisWorkbook.Save 'I was saving the results, I don't know if you need this
ThisWorkbook.Close 'I was closing my Workbook
2) In the Windows system, I was using a tool (installed usually with the system) called Task Scheduler, whose executable lies into the system folder (C:\Windows\System32\taskschd.msc) and it's really intuitive and easy-to-use. I have scheduled a task every 5 minutes which consisted on opening the workbook (once this was done, the open-workbook-event macro was triggered so my procedure was called, and after its execution the Workbook was closed and saved with the two lines of code I have posted you above).
Even if this is just my opinion (that I cannot prove with technical evidences), I don't trust too much the Application.OnTime in the long-term; it works fine for a little task every 10 seconds for a few minutes, but when the macro should be running regularly and you want to avoid seeing that, once every 5 hours, the Excel process crashes... then I would suggest to let the scheduling task to the Microsot tool rather than to the Excel application method.
MY EXPERIENCE
- my Excel, with the OnTime method in the macro, was crashing in a period between 1 hour (minimum crash) and 7 hours (maximum length of time before crashing). I was forced to open a distance connection from home and running it in the morning before to go out, to make sure the job was done before I got at work.
- my same macro, with the procedure I have described you above, never crashed anymore. I believe the system process is much more reliable than the Excel's one (but again, I don't have any evidence to prove you this so don't take it as gold).

vb.net writing background multithreading

My application will creates an Excel from DB, creating an excel file takes few minutes of time and till that time the user dont want to wait for the excel to complete, he should start working with the application. Once the excel have been completed the appilcation should po-up message saying, 'Report Sucess'.
can any one tell me how to do this, whtr background thread will help me in this ?
if yes pls provide me some sample, newbie to threading....
It depends what you do during the Excel creation.
A very simple and effective way to create and control a background thread is using a BackgroundWorker.
It very easy to implement.
And it's thread safe
You can find a working example I've prepared (BackgroundWorkerDoStuff).

VBA maintaining the program in memory

Sorry I don't know if this is something simple, or even where the problem fits in the greater scheme of programming.
So in my unsophisticated ways, my programs have always been of the scheme: 1. start program, 2. wait while program runs, 3. program is done and gone.
What I am doing now is creating a table from a long list of transactions (10,000s of). The table has several combo boxes for the user to select filters. Right now, every time the user changes a filter, the entire log is re-processed, which takes half a minute or a minute.
What I would rather do is have the trade log held in memory, or somehow latently but more immediately available. But not have the program "spinning" in the background. So the user could go about using Excel unaware that the program is ready in the background in case they want to update the table later, or not.
Does that make sense? If it can't be done in VBA, I'd still be curious how it would be done in another environment, say C#, if it could be. Thanks.
If the frequency of updates to the options trade is low enough you could separate reading and processing the option trades from the filtering process:
Step 1 - Refresh - read the logs and process them, storing the results in global containers (arrays, collections, dictionaries, objects ...)
Step 2 - User requests - show form - user chooses filters - show/store results extracted from the global containers.
There are several options
Firstly, is the code correctly structured? For example, do you really need to re-process everything or can a re-write be more efficient?
If you cannot avoid resource intensive code, notify the user with a progress bar or message. Also consider the use of DoEvents which frees up the operating system so that Excel can process other events.
DoEvents is slow and dirty. Even better look at this link DoEvents is slow!!! Here are faster methods
Rewrite your code to work asynchronously. Create a class, a handler and deal with each transaction asynchronously.
You could write some VBScript/Javascript and push the task out to run independently of Excel/VBA. Eg there's an example Here
Don't use VBA :)
Edit: How are you filtering? If you're iterating through thousands of items in an array testing for criteria it can be very slow. Excel's Advanced Filter is very quick and could process hundreds of thousands of rows with multiple criteria quickly.
When a macro in Excel VBA runs, the user cannot use Excel anymore, running the VBA "stucks" the whole program.
Here are a few tips to find a workaround for your problem :
Keep the vba running : load the data a first time when launching the combobox and then display results to the user every time he asks for but keep a combobox loaded so that vba keeps its context and memory
Load the data in Excel Worksheet, even hidden and then use it when the user asks for some data
Give us more info on what you are doing, from where you are loading the data, how you can cache it, what is your current code, what you tried... so that we can help you more
Regards,
Max

How can I protect a process I start from within my vb.net program?

I've created a small application that basically reads and writes to a single Excel.exe process. It's basically a timer that records the time I use on projects and then store it in an Excel sheet. This works great, however, I've noticed that if I open Excel manually, work on some sheets and whatnot, save and exit etcetc, the process my software use gets broken or something. The same thing that happens if I manually close the excel.exe process and my software doesn't "know".
So I was wondering if it's possible to protect the excel.exe process somehow? To make sure it can't be closed or tampered with in the meantime?
Let me suggest an alternative approach that does not require you to have an Excel process running all the time (after all, this also consumes a lot of system resources):
Let your application record your information. Every now and then -- for example, after a work entry has been finished or a specific time has elapsed -- open the Excel sheet, write the data, and close it again (also closing the Excel process that you are automating). This save operation should not take more than a few seconds and it will (mostly) prevent the problem you are experiencing.
In fact, since Office automation is always a bit painful, an even better way would be to output your data without requiring an Excel process. To do this, you could use
one of the third-party Excel libraries available for .net,
a CSV or HTML file, which can be opened by Excel, or
open the Excel file as a database with ADO.NET.
You cannot protect a process, but you can check the process.HasExited property to find out whether the process has terminated and take action based on that.
Add an exception handler. Either call non-throw methods if possible.

How to allow users to quit out of long-running VBA tasks?

I have a routine that examines thousands of records looking for discrepancies. This can take upwards of 5 minutes to complete and although I provide a progress bar and elapsed time count, I'm not sure I want to encourage folk pressing ctrl-break to quit the report should it be taking longer than expected.
A button in the progress bar won't work as the form is non-modal, so is there any neat way of allowing users to quit in this situation?
You need DoEvents and a variable whose scope is greater than the scope of what you're running. That is, if it's just a procedure, you need a module level variable. If it's more than one module, you need a global variable. See here
Stopwatch at DDoE
Normally, the VB engine will tie up the processor until it's done. With DoEvents, however, VB allows the processor to work on whatever is next in the queue, then return to VB.
I don't think there is a way to do it like you would want it to work. VBA is a scripting language so when you start your procedure, it's gonna run until it's done. If you had another button somewhere that even WOULD let you click it while the original procedure was running, I'm not sure how you would reference that procedure and stop it.
You could do something like ask the user if they want to contine, but that would make it run even longer.
Also you could have your procedure check for a condition outside of Excel and keep running as long as it's true. Something easy might be check if a certain text file is in a folder. If you wanted the procedure to stop, open the folder and move the file. On your loop's next iteration, it wouldn't see the file and stop running. Cludgy, inefficient, and not elegant, but it would work. You could also have it check a cell, checkbox, radiobutton, basically any control in another Excel sheet running in another instance of Excel. Again cludgy.
CTRL+Break works. Accept it and move on. One neat trick about that though, is that if you password protect your code and they hit CTRL+Break, the debug option is unavailable and they will only get Continue or End.
If this is code that is run frequently, have you considered scripting something that runs it during times when a human is not using the computer? I used to run telnet screen scraping macros that would take hours to go through our widgets, but I always had them run either on a separate computer or when I wasn't there (nights/weekends).