Code executing too fast -- causes errors

Z

zSplash

Hej, Guys!!

Back in December, I had a similar problem with an autoMacro, but now I'm
running into this problem with regular macros. Is this a known "bug", or am
I doing something drastically wrong in my coding? (or haven't I explained
it well enough to know!!)

The problem is that my code "runs too fast" to accomodate the changes it is
causing to the document. I deduce that from the fact that if I just put a
msgbox at the troublesome code, the routine works perfectly. When I take
out the msgbox, there are problems that result. I have tried Helmut's great
suggestion (for the autoMacro, anyway) of using a timer (i.e., '
Application.OnTime When:=Now + TimeValue("00:00:01"), Name:="continue"), but
that doesn't resolve it.

Can anyone offer any suggestions or direct me to any on-line help??

TIA
 
J

Jezebel

What sort of errors are you getting?

A couple of methods that might help --

1. Make sure all your updates use Range objects rather than the Selection
object.

2. Run the macro with ScreenUpdating off, or better yet, with the
Application not visible. (But make sure your error-handling switches it back
on!)
 
H

Helmut Weber

Hi zSplash,

there are several ways to slow down code.

I think, a loop with gettickcount
and doevents might do the trick.

Pseudocode:
Public Declare Function GetTickCount Lib "kernel32" () As Long
' -------------------
t = gettickcount
while gettickcount < t + 1000
' milliseconds
doevents
wend

For checking if a document has been successfully processed,
you may find this helpful, too.

http://groups.google.de/group/micro...blic.word.vba.*&rnum=2&hl=de#7a68fcec443bef06


--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 
J

Jezebel

Really shouldn't need to do it though. Speed should be an issue only in
relation to graphic refreshing, which should be controllable through the
graphic accelerator settings.
 
J

Jonathan West

Jezebel said:
Really shouldn't need to do it though. Speed should be an issue only in
relation to graphic refreshing, which should be controllable through the
graphic accelerator settings.


Unfortunately this is not so. Repagination, renumbering, updating dialogs,
and returning correct information from the Information property are all
things which sometimes need you to give Word a moment to catch up with what
you are doing. I have two techniques I use regularly and one more
occasionally

1. In many cases, just scattering a few DoEvents commands around the program
can do the necessary. DoEvents forces the program to temporarily cede
control of the computer to allow the Windows message queue to be polled.
Often one DoEvents command is not enough - at key points you might need to
add several consecutive ones.

2. If a UserForm is being displayed showing progress of a long job, I use
the Repaint method to refresh the UserForm, followed by some DoEvents
commands so that the graphics system is given the opportunity to act on the
command.

3. If a longer delay is needed, then I put the following declaration at the
start of a module

Private Declare Sub Sleep Lib "kernel32" ( _
ByVal dwMilliseconds As Long)

and call it for a short delay like this

Sleep 100 ' inserts a 0.1s delay


--
Regards
Jonathan West - Word MVP
www.intelligentdocuments.co.uk
Please reply to the newsgroup
Keep your VBA code safe, sign the ClassicVB petition www.classicvb.org
 
J

Jezebel

With all respect Jonathan, you're describing sloppy coding practices. As
mentioned, graphic events (like repagination, etc) are better managed by
switching off the GUI than by the sort of cludges you're recommending.
"Scattering a few DoEvents commands around the program" is an extremely
dubious practice (unless you're also diligently switching off every possible
source of interfering input ...)
 
J

Jonathan West

Jezebel said:
With all respect Jonathan, you're describing sloppy coding practices. As
mentioned, graphic events (like repagination, etc) are better managed by
switching off the GUI than by the sort of cludges you're recommending.
"Scattering a few DoEvents commands around the program" is an extremely
dubious practice (unless you're also diligently switching off every
possible source of interfering input ...)

Turning off screen updating often doesn't affect the kinds of things I have
described. Using ranges sometimes does not affect this. In any case, it can
happen that you must use a selection or at least move the view in order to
do something (e.g. find the horizontal or vertical position of some text on
the page). An intensive macro often doesn't cede enough CPU time to allow
for UserForms to be updated. DoEvents allows time for the necessary catch-up
by Windows for these kinds of cases.

I'm perfectly happy to consider other better ideas if suggested to me. I
don't regard telling the user to change Windows system settings in order to
run a Word macro to be an acceptable solution for an application intended to
be run by others.

Do you have any ideas you would like to share?


--
Regards
Jonathan West - Word MVP
www.intelligentdocuments.co.uk
Please reply to the newsgroup
Keep your VBA code safe, sign the ClassicVB petition www.classicvb.org
 
H

Helmut Weber

Hi everybody,

by the way, I am reluctant to recommend sleep,
as I don't know what it really does.

What process is put to sleep?
What happens during sleeping time?

If nothing happens, then it would be pointless to call it,
and it would have an effect only in so far,
as time is needed for calling and ending sleep.

I'm almost sure, but not quite,
that I don't understand "sleep".

--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 
J

Jonathan West

Sleep suspends execution of the current thread. Since the whole of a VBA
program normally runs in a single thread, it effectively suspends execution
of the entire program.

--
Regards
Jonathan West - Word MVP
www.intelligentdocuments.co.uk
Please reply to the newsgroup
Keep your VBA code safe, sign the ClassicVB petition www.classicvb.org
 
H

Helmut Weber

Hi Jonathan,
it effectively suspends execution of the entire program.

so what is it good for then but to give the
human looker-on a coffee-break?

--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 
J

Jonathan West

Helmut Weber said:
Hi Jonathan,


so what is it good for then but to give the
human looker-on a coffee-break?

Commands from Word to the graphics subsystem are executed in a separate
thread. If the main thread is suspended, the CPU is freer to handle such
calls.


--
Regards
Jonathan West - Word MVP
www.intelligentdocuments.co.uk
Please reply to the newsgroup
Keep your VBA code safe, sign the ClassicVB petition www.classicvb.org
 
Z

zSplash

Thanks so much for the suggestions -- all of you. I will try what you
suggest and see what works. You guys are the best!!

st.
 
T

Tony Jollans

I'm clearly late to the party on this one and am not totally convinced by
all that has been said but ...

Automacros at startup can have timing problems because several things are
all happening at the same time and not necessarily in the same order, but
normal running code shouldn't exhibit this kind of behaviour.

Can you give an example of something which fails to run even with a delay.
It seems to me than if an explicit delay doesn't solve your problem then a
contrived one won't either and your problem may, in fact, be something else.
 
J

Jezebel

I think you're confusing several issues here. Code 'running too fast' can be
an issue only if there are separate threads failing to keep pace with each
other. "An intensive macro often doesn't cede enough CPU time to allow for
UserForms to be updated" simply makes no sense in the Windows OS. Nor does
would the updating of the UserForm interfere with the running of a macro,
anyway (which was the OP's original issue).

DoEvents is specifically dealing with the Windows events queue (by
definition).

If screen updating is a problem in the document itself, you can hide Word
entirely -- which improves performance in any case -- but it's also
indicative of poor graphic settings, as you yourself have suggested in other
contexts.


Perhaps you can post a sample of code that you find needs to be slowed in
order to run correctly?
 
J

Jonathan West

Jezebel said:
I think you're confusing several issues here. Code 'running too fast' can
be an issue only if there are separate threads failing to keep pace with
each other. "An intensive macro often doesn't cede enough CPU time to allow
for UserForms to be updated" simply makes no sense in the Windows OS. Nor
does would the updating of the UserForm interfere with the running of a
macro, anyway (which was the OP's original issue).

It might make no sense, but it happens!
DoEvents is specifically dealing with the Windows events queue (by
definition).

If screen updating is a problem in the document itself, you can hide Word
entirely

Not an option if the macro is being run from within Word. In such cases, you
need a dialog box that gives an indication of progress.
-- which improves performance in any case -- but it's also indicative of
poor graphic settings, as you yourself have suggested in other contexts.

Nonetheless, even with updated drivers and optimized settings, this problem
occurs. I'm not interested in theories that say that something ought not to
happen when I've seen that it does.
Perhaps you can post a sample of code that you find needs to be slowed in
order to run correctly?

Later today I'll see if i can find time to put a sample together.

--
Regards
Jonathan West - Word MVP
www.intelligentdocuments.co.uk
Please reply to the newsgroup
Keep your VBA code safe, sign the ClassicVB petition www.classicvb.org
 
J

Jonathan West

OK, here's a simple sample

Create a UserForm. Put a label and two commandButtons on it. Make the
caption of CommandButton1 "Start" and the label of CommandButton2 "Stop"

Add the following code to the UserForm

Private mFlag As Boolean

Private Sub CommandButton1_Click()
mFlag = True
Do While mFlag
ActiveDocument.Range.InsertAfter "a"
Label1.Caption = ActiveDocument.Range.End
DoEvents
Loop
End Sub

Private Sub CommandButton2_Click()
mFlag = False
End Sub

Create a new blank document and run the form. Click Start, and see the
number of characters increment. Click Stop to stop it.

Now comment out the DoEvents command and repeat the experiment. You'll find
that Clicking Stop now has no effect, and you'll need to press Ctrl-Break in
order to break into the macro.
 
J

Jezebel

That's a simple and obvious example of what DoEvents is for: to give the
code a chance to process the message queue.

Do you have an example of code that needs to be slowed down in order to run?
 
T

Tony Jollans

Hmmm...

This is a separate issue - and a correct use of DoEvents.

Once Start has been pressed the code runs and control is not passed back to
the UI. The pressing of the stop button is a queued event which will be
processed only when control is ceded by the loop. This is not a timing
issue - at least not in the sense I understand the original question to have
been.
 
J

Jonathan West

Jezebel said:
That's a simple and obvious example of what DoEvents is for: to give the
code a chance to process the message queue.

Do you have an example of code that needs to be slowed down in order to
run?


Yes. Take a look at the code example in this article

Controlling the Printer from Word VBA
Part 2: Using VBA to control Duplex, Color Mode and Print Quality
http://pubs.logicalexpressions.com/Pub0009/LPMArticle.asp?ID=116


--
Regards
Jonathan West - Word MVP
www.intelligentdocuments.co.uk
Please reply to the newsgroup
Keep your VBA code safe, sign the ClassicVB petition www.classicvb.org
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top