Hi All,
Please accept my apologies for a rather lengthy post,
I'm not a lover of OnTime and, in this case, it doesn't seem workable.
Firstly, I can only make the OnTimed macro run at all if it is in Normal (I
haven't tried a different global template). Where did you put the code,
Beth? The OnTime instruction just seems to have no effect if the macro it is
trying to fire is in the document with the FormFields. Secondly, when I get
it to run by placing it in Normal, the FormField is not exited.
Both with this and the original problem, there seems to be a conflict
between FormFields and certain other actions; I really wish I understood
these things but can find no information at all.
My best guess is that when exiting a formfield, the action of entering the
next is somehow queued up waiting to run and that stops some other things
working - other things which also, perhaps, queue up in some way. When (by
accident or design) one of the queued actions is actioned or otherwise
released, the various other actions are then free to run (if they have been
remembered). There does seem to be a catch however ...
It seems that multiple DoEvents (and it does need more than one - whether
it's just a timing issue or whether there are in fact events which queue
further events or some other odd explanation, I don't know) will eventually
release whatever lock there is and the document can be persuaded to close
but when it does close it appears that it will return a "command failed"
error if it has returned one before.
In my test document ...
1. This fails
Sub ExitTest()
Documents.Add
DoEvents
ActiveDocument.Close
End Sub
2. This appears to work every time
Sub ExitTest()
Documents.Add
DoEvents
DoEvents
ActiveDocument.Close
End Sub
3. This closes the document but continues to loop and tries to close the
document with the formfields as well - reason being that the successful
close returns 'command failed'
Sub ExitTest()
Documents.Add
On Error Resume Next
Do
DoEvents
ActiveDocument.Close
Loop Until Err.Number = 0
End Sub
4. This gets round the above error and stops when the error is something
else (424 Object required)
Sub ExitTest()
Set newdoc = Documents.Add
On Error Resume Next
Do
DoEvents
newdoc.Close
Loop Until Err.Number <> 4198 ' Command failed
End Sub
5. This also gets round the error using a slightly different technique
Sub ExitTest()
Documents.Add
newdoc_name = ActiveDocument.Name
On Error Resume Next
Do
DoEvents
ActiveDocument.Close
Loop While newdoc_name = ActiveDocument.Name
End Sub
In Fuzzhead's document that Greg sent me, all the above fail and it appears
that the UserForm is an extra complication. Wrapping the code with Me.Hide
and Me.Show makes it work but introduces other problems to do with the order
of events and the display of the message box.
It does seem that hiding the userform is necessary so the easiest course of
action is to delay closing the document until the form is hidden later; this
requires the following changes (which I have tested in form frmWC but will
also be needed in frmCorc and anywhere else the code is duplicated).
1. Make oScratchPad a module level variable. Add at the beginning of the
module (after Option Explicit):
Private oScratchPad as Word.Document
and remove the definition from the spellcheck code in Test3_Click.
2. Remove the close of the scratchpad from Test3_Click. Although not
strictly necessary, I have hidden the document in my testing - to do this,
add this line where the Close was:
oScratchPad.Windows(1).Visible = False
3. It is possible that a user may click on "Spell Check" twice. If they do
that now there will already be a scratchpad document the second time and
opening another will leave the first one orphaned. To avoid this and just
unhide the previous document, change the open from:
Set oScratchPad = Documents.Add
to
If oScratchPad Is Nothing Then
Set oScratchPad = Documents.Add
Else
oScratchPad.Windows(1).Visible = True
End If
4. Lastly, after the form is hidden - that is in two places, CmdOK_Click and
CmdCancel_Click, add code to close the scratchpad if it is open, as per one
of the solutions above - I chose this one:
Me.Hide ' this line is there already
If Not oScratchPad Is Nothing Then
On Error Resume Next
Do
DoEvents
oScratchPad.Close wdDoNotSaveChanges
Loop Until Err.Number <> 4198
On Error GoTo 0
End If
This appears to work in my brief test but does need proper checking. It
would also be wise to add some error checking in case there is some other
error on closing - although unlikely a different error could cause an
infinite loop.
Hope this helps - and if anybody has a proper explanation which is better
than my work of fiction I would love to know what is really going on.