While working with Excel, I have many times faced the problem with Screen Refreshing.
Most of the time, in order to speed up VBA, programmers will use Application.ScreenUpdating = False. This will temporarily (until cancelled) stop screen refreshing. Unfortunately, there are cases, such as implementing progress bar, when you actually want to show some progress to the user. The problem is that the already mentioned command has stopped all screen refreshing.
This means, that even if on your UserForm you call a command to change a label (e.g. which would state Processing transaction 15 of 250) but you simply cannot get it to display.
What some people do in this case, is to temporarily enable ScreenUpdating, and right away disable it. This procedure is unfortunately unreliable, as if you have some difficult procedure (inserting complex formulas into cells) you are not guaranteed all the time that it will also refresh the label itself. Also the problem with this approach is, that you repaint not only your desired UserForm, but also Worksheet as well, and therefore this 'refresh' slows down your code quite a bit.
How can you refresh UserForm without refreshing the whole Excel?
The answer is simple.
Let's say that your userform is named frm_Main, so then in your VBA code you can simply call frm_Main.Repaint.
Simple as that!
Related
I want to ask about something, that can probably get pretty complex. I'm working on an interactive presentation with some game elements (stuff that use variables, a timer, score, etc.) and I've noticed that any changes a macro makes (changing the string in a text box, disabling certain shapes) when you run a slide show remain after the slide show has finished. Given that the presentation and the games therein are made to be played multiple times, I would like to avoid having the user click "Undo" a million times or closing and opening the presentation again. I am not sure how to go about this, but I've had a few ideas:
The first one was to track every change that's being made, while the game is running and then have a macro use the "Undo" command the required number of times, once the slideshow is stopped. Creating an Event Handler however proved to be rather complicated. I'm not that well versed in VBA and reading how many declarations, classes and whatnot have to be made, the fact that I cannot find in the reference what the Event for simply ending the slideshow is (that is, when the user presses Esc, not when the last slide has been reached) not to mention the fact that it's very easy to make a mistake that can render all of that code useless, makes me think this is needlessly complicated just for a single event.
Another idea was to set the initial values of the properties that are to be changed during the game, along with the needed variables at the start of the game, so that no matter what changes are made in the presentation, the values will always be reset when running it, although that would make it tedious to tweak things and make big changes to the game, when needed.
Can you give me some suggestions on how I should go about this problem? Which method would be better? Is there some way to make it so that nothing a macro does during a slide show makes actual changes to the presentation itself? I'd very much like to hear your thoughts.
Thanks!
There are a half-dozen answers to this. "Open a second instance" "Have a pause" Etc. I'm not looking for that.
I'm looking for the user of the workbook to be able to manipulate the workbook while the macro is running. I've seen this working before, where the user could scroll around, change tabs, even add and remove data, all while the macro was running. Unfortunately, I couldn't get permission to look at the code (And committing CFAA violations ins't my cup of tea), so I have no idea how they did it.
How can you enable a user to edit the workbook as macros are running? For a specific example, I have Conway's Game of Life running. Users select cells to flip live/dead, then can run a macro to run the entire thing. I think it'd be nice for users to be able to change cells as the macro is running. (which is a second on select macro)
Thank you
Sorry just reread the question. I wouldn't expect the permutation to run for very long - not long enough to interrupt really.
But if it does, then the advice about using lots of DoEvents stands.
The other option is that you can use the OnTime event to have a "heartbeat"
VBA Macro On Timer style to run code every set number of seconds, i.e. 120 seconds
You can set the timer to say 3 seconds. Every time the OnTime event occurs you do one step of your permutation. In the three seconds in between they can edit.
Refactor your macro to use Events. In which case, you would have a series of event handlers (instead of one monolithic macro) to respond to various triggers. This is assuming that the macro is influenced by what the user is doing in the worksheet.
One way of (sort of) doing this is to use a Modeless Userform (UserForm.Show vbModeless)
The user form stays visible but the VBA stops running when the form is shown and the user can then interact with Excel. Then when the user clicks a button on the form the code behind the button starts running again.
So in reality the user is either interacting with Excel or interacting with the form ...
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.
Symptoms
After completing a VBA macro that runs whenever a calculation event occurs, my workbook enters a strange semi-lock state. The symptoms are:
When highlighting any cell with contents, the formula bar or window flickers several times per second.
I can enter formulas and formula arrays in any blank cell and calculation proceeds as normal, although flickering continues.
Switching between auto/manual calculate has no effect on the flickering.
The array formulas associated with the calculation event take on a strange property: While editing them in the formula bar, if I press ENTER nothing happens. Normally for an array formula I would get an error, but for these, the cursor just stays in the formula editing window unless I press CTRL+SHIFT+ENTER. See below for relevant details on the application.
For context:
My application is a VBA add-in that uses UDF's to pull read-only data from a remote MySQL server. The workflow involves piggy-backing on the calculate event in order to get around the fact that excel UDF's can't alter the size of the formula that is calling them. The process goes:
user enters formula
formula creates a 'query' item that is stored in a global collection
upon calculation, a subroutine processes all the queries, sends SQL queries to the remote database, receives the response, resizes the formula region to fit the size of the returned data, and stores the returned data in another global collection
when the calling region is resized, the formula function automatically runs again. This time, it sees that data is waiting in the second global collection and that the data is the right size, and it writes the data to the worksheet, preserving the formula
Based on the debug window, it looks like my calculate event has finished when the flickering begins to occur. All of my global collections are empty. I'm not sure what the application is doing when it locks in this way or how to get more data on the problem. It only occurs occasionally.
Has anyone encountered something like this before?
Hopefully it helps someone who has the same or similar problem. In my case there were no formulas in workbook and no calculate events. Still - after macro executed, values populated by the macro in formula window were flickering.
After debugging, it came out that on line with array paste, macro was repeatedly going back to start of procedure, while pasting only part of data. After I fixed calculation of array values, so that arguments for timeserial functions were correct, pasting complete array succeeded without retreating to start of sub.
This is a distilled form of a problem I'm having with a real application. Under certain circumstances, the initialization/activation code of a userform might result in the form losing its ability to correctly process tabs and enters: rather than switching between controls, these keys are passed to the controls themselves (even if they have TabKeyBehavior set to False). The simplest way I've found to systematically reproduce the problem is by having this at activation time:
Private Sub Userform_Activate()
Application.DisplayDocumentInformationPanel = True
End Sub
which seemingly causes Excel to "half-steal" the focus from the userform, so to say: the userform remains focused but tab/enter processing fails. The problem immediately goes away by switching to some external app and getting back to Excel (pressing ALT+TAB twice, for instance.)
Steps to reproduce the problem:
Download tabnotworking.xlsm.
Open tabnotworking.xslm.
Enable macros.
Click on the "Launch UserForm1" button.
UserForm1 is displayed and the textboxes accept input from the user, but tab/enter does not work as expected.
Press ALT+TAB twice or click on some external app and get back to the form: now tab processing works OK.
Once tab/enter processing has been restored, further usage of the form, including relaunching it, seems to work OK (most of the time). To reliably reproduce the problem again, close the book and start from step 2.
There are numerous references on the Internet to problems with tab processing seemingly related to this one, but no actual solution. Any clue on what's happening and how it could be solved? Thank you,