Woo, Your are a GENTELMAN "with capital letters" and scholar for spending so
much time and explain this so well...
Yes I have only a single USERFORM and Multipage/Tabs, 12 pages/tabs on it
and only 3 of these tabs are visible all the times and the rest are
Visible=False. Actually the code prints more than 30 different documents and
more than 20 documents will be printed "by selection" using information
collected from the first 3 pages visible and 12 of the other documents need
extra info that are being collected from those hidden pages/tabs after making
them visible to the user...
Now wouldn’t you agree with me if MS would have allowed “Optional†that the
user invoke a subroutine/function when clicking the X button?
Regards
--
Jeff B Paarsa
:
Jeffery,
I'd recommend several changes to avoid this problem:
1. Stop using "magic forms". (There was a 'rant' on "magic forms" posted
here recently that is probably worth searching for and reading.) Instead,
instantiate an instance of the UserForm object and refer to this object
explicitly in your code.
2. Stop using "ActiveDocument". Instead, instantiate an instance of a
Document object and refer to this object explicitly in your code.
3. Ensure that the code in the UserForm code module deals _only_ with events
that occur when the UserForm is displayed. Place any other code - especially
code that manipulates the document or the application - in a standard code
module.
4. Use a flag of some sort (usually a Public Boolean variable) to capture
which button is clicked to dismiss the UserForm. Actually, you really only
need to be concerned about capturing when the "OK" button (or whatever it is
in your specific application) is clicked. If you default the "flag" to the
false and set it to true in the "OK" button Click event, any other method of
dismissing the UserForm will be produce the same result.
The general structure that I use is as follows:
In the Declarations section of a standard code module-
Public boolNewDoc As Boolean
Dim myDoc As Document
Dim myForm As UserForm1
In the procedure that "launches" the template (usually an AutoNew macro)-
Sub AutoNew
boolNewDoc = False
Set myDoc = ActiveDocument
Set myForm = New UserForm1
Load myForm
myForm.Show
If boolNewDoc = True Then
CollectUserFormValues
End If
Unload myForm
Set myForm = Nothing
If boolNewDoc = True Then
BuildDocument
Else
myDoc.Close wdDoNotSaveChanges
End If
End Sub
An explanation of the above:
CollectUserFormValues is a procedure to collect the values entered in myForm
before it is removed from memory. It uses a series of type-appropriate
variables (usually Strings but sometimes Boolean) to gather the values for
later use and refers to "myForm" explicitly throughout.
BuildDocument is a procedure for actually building the document using the
values gathered in CollectUserFormValues. It refers to "myDoc" explicitly
throughout.
Unloading myForm and setting it to the keyword "Nothing" ensures that the
instance of the UserForm is removed from memory cleanly.
As discussed in 4 above, the Boolean variable "boolNewDoc" is defaulted to
false and set to true in the Click event for the "OK" button on the UserForm;
the code for doing this is as follows:
Sub btnOK_Click()
boolNewDoc = True
Me.Hide
End Sub
The code for the Click event for the "Cancel" button can be as simple as:
Sub btnCancel_Click()
Me.Hide
End Sub
However, I don't really like relying on default values and generally try to
be explicit as possible. (I also recognise that sometime users do stupid
things without meaning to and try to do as much as I can to save them from
themselves.) Therefore, my standard "Cancel" button Click code usually looks
like this:
Sub btnCancel_Click()
Dim myResult as Long
myResult = MsgBox ("Are you sure you want to cancel this document?",
vbYesNo, "Cancel Document")
If myResult = vbYes Then
boolNewDoc = False
Me.Hide
End If
End Sub
However, note that by defaulting boolNewDoc to false, when the UserForm is
dismissed using the [X], the code still executes normally using a value of
false: the UserForm values are not collected; and the document is closed
without saving the changes.
One final point: I think you may be confused about how an AutoClose macro
works. This macro runs when the *document* is closed, not when the *UserForm*
is closed. Therefore, dismissing the UserForm - using whatever method - does
not cause the AutoClose macro to execute.
In addition, there are a few problems that I see with the structure of your
AutoClose macro. First, it appears to me that what you are trying to do is to
shut down Word entirely when the document is closed (or rather when the
UserForm is dismissed without clicking the "OK" button). I would argue that
this is not a good idea because the user may have Word open for other reasons
than to simply run your template. Killing Word completely would undoubtedly
generate a complaint or two in this instance - unless, of course, you can
guarantee that the only reason Word would be running is to run your
template...
Second, because an AutoClose macro runs when the document is closed, it
seems a bit pointless to write an AutoClose macro that closes the document.
However, it appears that what you are trying to do is close the document in
such a way that the user is not prompted to save the changes to the document;
the document simply closes and any changes to the document are lost. I am
unsure as to exactly why you would want to do this unless you don't want
users to be able to save a soft copy of the document *ever* - and in this
case there is nothing to stop the user from saving the document just prior to
closing it. However, closing the document when the UserForm is dismissed
without using the "OK" button _does_ make sense and can be achieved using the
solution above.
Finally, your "Application.Quit" will never execute no matter how hard you
try. This is because once the document is closed - and the first line of code
in your AutoClose macro does just that - the document is no longer in memory,
so the code cannot be accessed. To see what I mean, put the following code
into a standard module a template:
Sub AutoClose()
ActiveDocument.Close wdDoNotSaveChanges
MsgBox "Document closed."
End Sub
Now create a new document from the template and then close the document.
What will probably happen is that you'll get an error, but I can guarantee
that the message box will never be displayed. This will also happen even when
you just close the template or if you put the code directly into a document.
Once the object that contains the code is removed from memory the code
contained within the object is no longer available.
If you really, really, REALLY want to kill Word when your UserForm is
dismissed, modify this bit of my code:
If boolNewDoc = True Then
BuildDocument
Else
myDoc.Close wdDoNotSaveChanges
End If
to be:
If boolNewDoc = True Then
BuildDocument
Else
myDoc.Close wdDoNotSaveChanges
Application.Quit
End If
It will work, but it definitely won't be pretty - especially if there are
other documents open.
Having said all that I suspect that what your real goal is is to ensure that
when the UserForm is dismissed using any method other than clicking the "OK"
button, the document created from the launch of the template is closed
without saving the changes. The code I have provided should allow you to
achieve this goal.
Finally, I've read the article about intercepting the UserForm [X] button,
and I think maybe it's a little thin in that it doesn't explain what the code
actually does. In essence the code simply makes clicking the [X] button do
nothing. It does this by setting the Cancel argument of the QueryClose event
for the UserForm to True, which has the effect of _not_ dismissing the
UserForm. It's a useful hack I suppose and will achieve a semblence of the
desired result, but it's not the best solution IMHO in that it modifies the
standard behaviour of the [X] button in a way that may confuse the users.
Hopefully I have a provided a "prettier idea" for addressing this problem.
(And to address a couple of your other queries / comments: If by a
"multipage" UserForm you mean one that contains a MultiPage control, then I
can see no reason why either my solution or the intercept [X] button solution
wouldn't work. However, if you mean some sort of multiple UserForm
application, then you would, of course, need to apply the selected solution
to every UserForm. However, I don't necessarily see this as a "hole by
Microsoft" but rather suspect that the problem lies in your understanding of
AutoClose macros, as discussed above.)
--
Cheers!
Gordon
Uninvited email contact will be marked as SPAM and ignored. Please post all
follow-ups to the newsgroup.
:
Thanks again... I wonder if this works for my multipage UserForm? Should I
be putting the "QueryClose event" button on all the pages or only on one of
the pages i.e. first page... It seems the outcome is not going to be a
pretty solution. It seems this is another hole by Microsoft. Any prettier
idea?
--
Jeff B Paarsa
:
Maybe you need to make use of the information in the article "Intercept the
Close button (X) in the title bar of a user form" at:
http://www.word.mvps.org/FAQs/Userforms/InterceptCloseButton.htm
--
Hope this helps.
Please reply to the newsgroup unless you wish to avail yourself of my
services on a paid consulting basis.
Doug Robbins - Word MVP
Thanks for the response... but did not work... sounds like each time I
click