How to manage event for made a load bars in Access - vba

I created an application with Access (2013) with VBA. This application crawls a website and inserts some records into database. But it takes too much time.
My solution is to make load bars for waiting. But currently I use the event Form_Current(); and when I set the load bar's value (it's my function) setBarLoadValue (25) Nothing is displayed on the screen. Why ? Because my function run yet.
My question is: How I can manage the event to simulate a load bar in real time ? (Don't want to wait till the end of function to see 100%).

The following link has a beautifully designed Progress status bar. http://www.access-programmers.co.uk/forums/showthread.php?t=265537
The author of the code has provided a Class where you have a Form that acts as a Meter and you basically set the values. It could be real time enough, have a look. I use it in my application and works great.

Finally I found an solution !
Solution
Step1
You must enter this code in your code
DoCmd.SelectObject acForm, Me.Name
Me.Repaint
DoEvents
With this code, you display immediately the form
Step 2
Now, when you want to display something, you must just do that: DoEvents.
When you use DoEvents the form refresh and you can display the new state of the progress bar.
Note: This solution work with Access 2013. Maybe it's not supported with other version.

Related

Stuck in infinite loop. Any way to break vba into Code when Control+Break doesn't work

I have code stuck.
It might be in an infinite loop.
Not sure.
Is there a way to break the program to stop at the current line of code that it is running on?
I'd like to avoid shutting down excel because I want to be able to catch where in the loop it is, and by going into the code, I will be able to tell how much processing was done. I would like to break into the code, if possible.
It is stuck on hour glass.
Ctrl+Break doesn't seem to work
Seems like the running code has hijacked all the quota that cpu is giving to excel.
If there is nothing I can do now, is there something in the future I can do to where I can more easily break into the code?
I'm thinking that an intermittent wait within a loop might be a feasible solution.
In the future, include a DoEvents inside the loop. It will run a little slower, but you will be able to use Ctrl+Break to stop it from running.
Create a progress dialog when entering the loop and include a Cancel button. Within your loop check for the Cancel signal/event. This also gives you some flexibility on how you react to the Cancel - you could stop the loop and display key information in a new dialog box (for example).
Basic steps to achieve what I have described (not necessarily the most elegant or the most re-useable, but simple enough for those of lesser experience):
create a modeless (not modal) Form with either suitable labels or a progressbar item (for
visual effect). Include a public property (Boolean) for Cancel (e.g.
boolCancel)
Place a button on form and onClick set boolCancel = True
In your main code, show the form just before your problem loop.
while in your loop you can update some label or progress bar on the
form so that you have a visual indication of whether the loop is
doing something of value or if it is now simply spinning its wheels.
How you do this depends on what your loop is doing.
Also while in your loop check your boolCancel value. If true then
display any state information you want and break from the loop.
If your loop ends normally, hide/unload the progress dialog.

Let a Form stay on top even if ToggleDesktop() (shell32.dll) is called

is there anyway to capture and cancel or do something like me.activate when the show desktop event is triggered and make my form visible?
note:
The show desktop event is triggered by another app which is installed in some of my users pc. I am not trying to make my form always on top of other open windows.
Thanks in advance.
Alright, you mean to let your form stay on TopMost even if ToggleDesktop() in shell32.dll is executed.
By far I can say: there is none. They tried to experiment at codeguru but it seems there were no successfully results.

What is the bare minimum VBA "I'm busy" dialog?

I've got a macro in PowerPoint 2010 that links audio files to each and every slide. However, this takes some time, and although there is a status bar "linking files" progress, I would like something more In your face.
Caveat: I'm really not familiar with VBA or it's API.
What I want:
ImBusyDialog("Linking Files...").Open()
// Call Sub that does real work.
ImBusyDialog.Close();
and that's it. If there's something built in like the page loading spinner in IE, then great, if not, I'm happy with a simple message box. The important thing is that it require no user intervention.
Use the same logic as you do to set the status bar. Where you set the statusbar text, you'll simply add the appropriate code to call a status dialog box.
O'Reilly has a rather detailed description on how to build a status bar dialog box with a progress bar and everything. It is probably a bit overkill for what you want, but more to see what is possible in VBA: http://oreilly.com/pub/h/2607
Stackoverflow has dealt with this issue before as well with a relatively simple box you could easily modify to show which file is being worked on an any given moment: How do I create a status dialog box in Excel
The important code from the previous post:
Sub ShowForm_DoSomething()r
Load frmStatus
frmStatus.Label1.Caption = "Starting"
frmStatus.Show
frmStatus.Repaint
'Load the form and set text
frmStatus.Label1.Caption = "Doing something"
frmStatus.Repaint
'code here to perform an action
frmStatus.Label1.Caption = "Doing something else"
frmStatus.Repaint
'code here to perform an action
frmStatus.Label1.Caption = "Finished"
frmStatus.Repaint
Application.Wait (Now + TimeValue("0:00:01"))
frmStatus.Hide
Unload frmStatus 'hide and unload the form
End Sub
The O'Reilly solution certainly is an involved solution, but it seems the "prettiest" and would probably be very user-friendly. The SO solution appears to be much easier to implement though.

Add a spinning wheel while application is searching database

I have an application that searches in a database for some information.
Since the database is quite big, it sometimes takes a lot of time before the application returns the results to the interface.
I want to add some sort of spinning wheel to inform the user that the application is still searching the database and did not freeze. Once the results are returned, the wheel should disappear.
Any idea how to do this or is there a good tutorial explaining how to do this?
Have you considered changing the mouse pointer to the hourglass as this would be extremely simple to implement:
Me.Cursor = Cursors.WaitCursor
...Do your DB calls here...
Me.Cursor = Cursors.Default
However, I would agree that display a 'spinning wheel' is probably a little more user friendly and definately a lot more obvious. So, first get hold of an animated gif that suits your needs. Then create a form that has a picture box containing the image.
Once you have that you can show the form to the user and in the background do the DB work, once this has completed close the form.
Another alternative would be to use a rolling progress bar instead, so when it reaches 100% it cycles around again and keeps going until you close it.
EDIT:
One thing that I forgot to mention is that you will have to handle exception conditions. Lets say you set the cursor to wait, then an error occurs. The exception may bypass the code that resets everything. This leaves the user with a changed cursor and no means of changing it.
When I have done this kind of thing I have typically created a disposable WaitCursor class and then used something like this:
Using myWaitCursor As WaitCursor = New WaitCursor
...do something...
End Using
In the Dispose of the WaitCursor class you set the cursor back to default. The same would apply if you went down the route of using a form with an image or progress bar.
Find an animated gif of such a spinner, like this one. Put it in a PictureBox, set its Visible property to True when you start the job. Beware that you'll have to run the query in a worker thread to keep the animation alive and the user interface responsive. The BackgroundWorker class is good for that.
You could use the Environments Default wait cursor, which for Vista/7 is a circle with the outside spinning, or the XP tumbling hourglass.
You could launch your DB access on a BackgroundWorker and show an animated control such as a Marquee progress bar, or you could show a custom animation to show Busy status.

VBA Status Bar

I am working on a Word VBA macro app for 80 or so users. The office has high staff turnover, so training suffers, and so one of the self imposed requirements for this project is comprehensive, friendly documentation. However, to supplement this, and to save newbies having to open up a 100 page document when they want to try something new, I want a status bar on every userform (there are five) that provides contextual help. I find tooltips annoying.
I don't have a lot of experience, so I was wanting to
Essentially, I have a file containing every status string. (This is currently a text file, but I was wondering if I should use a spreadsheet or csv for ease of editing by other staff in future.) Every control has a MouseMove event which refers to a function: getStatus(cID) that opens the file, grabs the line and displays it in the status label. It also grabs a few parameters from the same line in the file, such as whether the label is clickable (to link to a page in the help file), and what colour the label should be.
So a few questions really:
Will the application be slow if a userform is constantly referring to a file? It feels fine to me, but I've been in it far too long, and I'm the only user accessing that file. There will be 80 constantly accessing it.
Is MouseMove over a control the best way? Should I instead use co-ordinates?
Most importantly (in terms of me having to do as little work as possible) is there some way to do this so that I do not have to have a MouseMove event on every single control? I have a good few hundred or so controls, each with their own identifier (well, not yet, but they will if this is the only way to do it). Maybe when the form loads I could load ALL the possible status lines so they're ready for whenever the control is moused over. But then, maybe the loading time is negligible?
Appreciate any ideas or thoughts - especially if VBA already has a whole range of functions to do this already and I'm just trying to reinvent the wheel. I can't use the application status bar, because the user rarely sees the application itself.
Thanks!
EDIT:
It is for both data entry, clicking around and a bit of document generation.
It is a controlled environment so macro security issues aren't a big concern for me - and if something goes wrong it's someone else's fault or problem :)
Is this data entry app or do they just click stuff? Because often the field with focus is different to the item the mouse is hovering over, this can cause a lot of confusion.
Constantly reading from a file is a huge waste of time and resources - it is much better to load them only once into an array or collection when the form is loaded.
On MouseMouse event is better than coordinates because you can move things around without worrying. It's a lot of code but you should be able to generate most of that if you have a list of control names because the code should be identical.
ie
Sub Control_MouseMove()
DisplayStatus(Control)
End sub
I would consider the StatusText property and ControlTipText property of controls for this kind of help.
StatusText
This example sets the status bar help text for the form field named "Age."
With ActiveDocument.FormFields("Age")
.OwnStatus = True
.StatusText = "Type your current age."
End With
ControlTipText
This can be assigned from the property sheet for the control.
Private Sub UserForm_Initialize()
MultiPage1.Page1.ControlTipText = "Here in page 1"
MultiPage1.Page2.ControlTipText = "Now in page 2"
CommandButton1.ControlTipText = "And now here's"
CommandButton2.ControlTipText = "a tip from"
CommandButton3.ControlTipText = "your controls!"
End Sub