WINWORD.EXE process deos not end after closing the user form?

J

Jeffery B Paarsa

Hello,

I have a Template named X.dot. When I double click on this template to
create a new document, I have noticed when I close the USERFORM PForms thru
using red X on top right corner of the USERFORM, I have noticed that
WINWORD.EXE statys live on the Processes tab in the Task Manager and a
resudue file of ~X.dot stays in the directory of X.dot. I am including my
AutNew and AutoClose macro here in this message... I don't know what I am not
doing right that WINWORD.EXE does not terminate and residue file stays in the
directory?

Any idea what not doing right?

Sub AutoNew()
Application.Visible = False
PForms.PVDate.Text = Date
PForms.MultiPage1.Value = 0
PForms.Show
End Sub
Sub AutoClose()
With ActiveDocument
.Close wdDoNotSaveChanges
Application.Quit
End With
End Sub
 
D

Doug Robbins - Word MVP

Try moving the Application.Quit outside of the With End With construction.

--
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
 
J

Jeffery B Paarsa

Thanks for the response... but did not work... sounds like each time I click
on the template for new doc and then close it the amount of leakage
increases... now my AutoClose look like this...

Sub AutoClose()
With ActiveDocument
.Close wdDoNotSaveChanges
End With
Application.Quit
End Sub
 
J

Jeffery B Paarsa

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?
 
G

Gordon Bentley-Mix

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.
 
J

Jeffery B Paarsa

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


Gordon Bentley-Mix said:
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.


Jeffery B Paarsa said:
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?
 
G

Gordon Bentley-Mix

Ahh, but MSFT _has_ provided a way to invoke a subroutine when the [X] button
is clicked: by writing code against the UserForm_QueryClose event. The
information provided in the "Intercept Close Button" article is not the sum
total of what can be done. That article just describes a way working with the
Cancel argument of this event to prevent the UserForm from closing - similar
to what I do regularly when validating the value entered into a TextBox. I
run validation code triggered by the Exit event for the TextBox, and if the
validation fails (for example, if I want a date entered and the IsDate
function for the .Value property returns false) I set the Cancel argument to
True so focus stays in the TextBox. However, I _have_ written code against
the TextBox Exit event that does nothing with the Cancel argument, as well as
against other events that does not use any or all of the arguments of the
event. (The KeyDown event comes to mind: It takes an argument for the Shift
key, but the code I was writing was concerned only with the Delete key, and
in that instance the Shift key doesn't come into play so I didn't have to put
anything in my code about it.)

Of course, if you follow my recommendations then it doesn't really matter;
the [X] button will work like a "Cancel" button because of the default value
for the "flag". However, I suppose you could put the "Cancel" button Click
event code into the UserForm_QueryClose event code as well...
--
Cheers!
Gordon

Uninvited email contact will be marked as SPAM and ignored. Please post all
follow-ups to the newsgroup.


Jeffery B Paarsa said:
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


Gordon Bentley-Mix said:
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.


Jeffery B Paarsa said:
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
on the template for new doc and then close it the amount of leakage
increases... now my AutoClose look like this...

Sub AutoClose()
With ActiveDocument
.Close wdDoNotSaveChanges
End With
Application.Quit
End Sub

--
Jeff B Paarsa


:

Try moving the Application.Quit outside of the With End With
construction.

--
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

Hello,

I have a Template named X.dot. When I double click on this template to
create a new document, I have noticed when I close the USERFORM PForms
thru
using red X on top right corner of the USERFORM, I have noticed that
WINWORD.EXE statys live on the Processes tab in the Task Manager and a
resudue file of ~X.dot stays in the directory of X.dot. I am including
my
AutNew and AutoClose macro here in this message... I don't know what I
am
not
doing right that WINWORD.EXE does not terminate and residue file stays
in
the
directory?

Any idea what not doing right?

Sub AutoNew()
Application.Visible = False
 
J

Jeffery B Paarsa

One last thing to ask you... If I may ask you... If I change my more than 500
lines of VBA code design for all these document templates that will be done
from Sub AutoNew, do I still need to do "Mr. Doug Robbins - Word MVP"
suggestions for intercepting X close Userform?

Still I think with a single option thru Property window Microsoft can give
the option of transferring the control to the VBA routine as an
Interrupt/Event being handled via programmer than completely taking it away
putting it into a rather tricking and obscure routine that can only be find
in the discussion group...

Regards,

Jeff B Paarsa

--

Gordon Bentley-Mix said:
Ahh, but MSFT _has_ provided a way to invoke a subroutine when the [X] button
is clicked: by writing code against the UserForm_QueryClose event. The
information provided in the "Intercept Close Button" article is not the sum
total of what can be done. That article just describes a way working with the
Cancel argument of this event to prevent the UserForm from closing - similar
to what I do regularly when validating the value entered into a TextBox. I
run validation code triggered by the Exit event for the TextBox, and if the
validation fails (for example, if I want a date entered and the IsDate
function for the .Value property returns false) I set the Cancel argument to
True so focus stays in the TextBox. However, I _have_ written code against
the TextBox Exit event that does nothing with the Cancel argument, as well as
against other events that does not use any or all of the arguments of the
event. (The KeyDown event comes to mind: It takes an argument for the Shift
key, but the code I was writing was concerned only with the Delete key, and
in that instance the Shift key doesn't come into play so I didn't have to put
anything in my code about it.)

Of course, if you follow my recommendations then it doesn't really matter;
the [X] button will work like a "Cancel" button because of the default value
for the "flag". However, I suppose you could put the "Cancel" button Click
event code into the UserForm_QueryClose event code as well...
--
Cheers!
Gordon

Uninvited email contact will be marked as SPAM and ignored. Please post all
follow-ups to the newsgroup.


Jeffery B Paarsa said:
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


Gordon Bentley-Mix said:
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
on the template for new doc and then close it the amount of leakage
increases... now my AutoClose look like this...

Sub AutoClose()
With ActiveDocument
.Close wdDoNotSaveChanges
End With
Application.Quit
End Sub

--
Jeff B Paarsa


:

Try moving the Application.Quit outside of the With End With
construction.
 
G

Gordon Bentley-Mix

Jeff,

You can use either one method or the other or both; they're not mutually
exclusive. The choice is really up to you (but personally I wouldn't mess
around with the [X] button as the cost / benefit is too low).

As for MSFT "hiding" stuff, I think you'll find that there is a huge amount
of functionality in Word and VBA that's not well advertised. (And in any
case, you will never find anything like this in the Properties window for a
UserForm or any other control, as the Properties window lists only
_properties_ not events.) What is required is a thorough understanding of the
Word object model and VBA itself, as well as a high level of curiousity and a
willingness to explore new solutions. I've been at this for a while now, and
I still learn new stuff every day - the QueryClose event being a perfect
example. But just because it was new to me it didn't throw me because I
understood how it worked at a basic level, and the rest is just details.
--
Cheers!
Gordon

Uninvited email contact will be marked as SPAM and ignored. Please post all
follow-ups to the newsgroup.


Jeffery B Paarsa said:
One last thing to ask you... If I may ask you... If I change my more than 500
lines of VBA code design for all these document templates that will be done
from Sub AutoNew, do I still need to do "Mr. Doug Robbins - Word MVP"
suggestions for intercepting X close Userform?

Still I think with a single option thru Property window Microsoft can give
the option of transferring the control to the VBA routine as an
Interrupt/Event being handled via programmer than completely taking it away
putting it into a rather tricking and obscure routine that can only be find
in the discussion group...

Regards,

Jeff B Paarsa

--

Gordon Bentley-Mix said:
Ahh, but MSFT _has_ provided a way to invoke a subroutine when the [X] button
is clicked: by writing code against the UserForm_QueryClose event. The
information provided in the "Intercept Close Button" article is not the sum
total of what can be done. That article just describes a way working with the
Cancel argument of this event to prevent the UserForm from closing - similar
to what I do regularly when validating the value entered into a TextBox. I
run validation code triggered by the Exit event for the TextBox, and if the
validation fails (for example, if I want a date entered and the IsDate
function for the .Value property returns false) I set the Cancel argument to
True so focus stays in the TextBox. However, I _have_ written code against
the TextBox Exit event that does nothing with the Cancel argument, as well as
against other events that does not use any or all of the arguments of the
event. (The KeyDown event comes to mind: It takes an argument for the Shift
key, but the code I was writing was concerned only with the Delete key, and
in that instance the Shift key doesn't come into play so I didn't have to put
anything in my code about it.)

Of course, if you follow my recommendations then it doesn't really matter;
the [X] button will work like a "Cancel" button because of the default value
for the "flag". However, I suppose you could put the "Cancel" button Click
event code into the UserForm_QueryClose event code as well...
--
Cheers!
Gordon

Uninvited email contact will be marked as SPAM and ignored. Please post all
follow-ups to the newsgroup.


Jeffery B Paarsa said:
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
 
J

Jeffery B Paarsa

Mr. Robbins,

Your advice was very helpfull and I was able to resolve my problem, but I
don't know how to "reply to the newsgroup"... If I click on Yes Button on the
bottom of your response where it says "Was this post helpful to you?"
followed by two button of Yes and No? is that what you like me to reply?
 
D

Doug Robbins - Word MVP

The request that replies should be sent to the newsgroup is to discourage
people from moving a thread from the newsgroup to a private email exchange
as by doing so, other newsgroup participants would be prevented from
learning from the exchange (unless of course, they do want to engage me to
provide assistance to them on a paid consulting basis).

Using a newsreader (Outlook Express) to access the newsgroups, I do not see
the Yes/No buttons that are present in some web based interfaces to the
Newsgroup Servers. I imagine the purpose of those buttons it to let others
know that the response that was given provided the information that the
original poster was seeking and they could be guided accordingly.

--
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
 
J

Jeffery B Paarsa

Thanks...
--
Jeff B Paarsa


Doug Robbins - Word MVP said:
The request that replies should be sent to the newsgroup is to discourage
people from moving a thread from the newsgroup to a private email exchange
as by doing so, other newsgroup participants would be prevented from
learning from the exchange (unless of course, they do want to engage me to
provide assistance to them on a paid consulting basis).

Using a newsreader (Outlook Express) to access the newsgroups, I do not see
the Yes/No buttons that are present in some web based interfaces to the
Newsgroup Servers. I imagine the purpose of those buttons it to let others
know that the response that was given provided the information that the
original poster was seeking and they could be guided accordingly.

--
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
 

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