After a while I have 20 docs opened, and because our PCs are spartan to say the least, it becomes impossible to do anything, appart from throwing out the bloody things. "
Aaaaack!!!
No doubt.
Rule #1 in programming (of course I am being facetious).
Understand Scope.
Corollary to Rule #1: Keep declared objects for only as long as you need them.
What I am saying is that you should NOT have those 20 docs. Why have them? So....get rid of them when you are done with them. Pseudo-code:
Code:
Sub cmdLetter_Click()
[COLOR=red]' assumes [b]Application[/b] object is previously declared and Set!!![/color red]
declare document object
set document object
do stuff with document object - wdDoc
now........
wdDoc.SaveAs Filename:=yadda
[b]wdDoc.Close[/b] ' document is saved and GONE
Set wdDoc = Nothing ' document [b]object[/b] - MEMORY - gone
End Sub
You need to understand the difference between a document you see in the GUI (Graphical User Interface) - Word - and a chunk of allocated memory assigned for it.
In other words, if you CLOSE the document at the end of each cmdLetter_Click, you will not have those 20 documents you say you have. If you destroy the document object (wdDoc) you will not have memeory issues from all of them cluttering up.
Plus, if you create the Application instance (wdApp)
once and simply do stuff with it, and cleanly QUIT it, and cleanly destroy the object (memory allocation), then you should not get those multiple Winword.exe. Simply because you did not create them in the first place. You used ONE.
OK.
"At the moment the user closes the userform by closing the window with "X". "
Technically, shrug...OK, but IMO, this is not a best-practice. In fact, I generally trap users clicking the "X", and make them explicitly tell me they want to close. If they answer yes, then I explicitly use Unload Me to cleanly unload the userform. The reason being is that someone may accidently click the "X". It happens.
In your case, as you are allowing multiple actions (multiple uses of cmdLetter_Click), I would definitely have a "Complete", or a "Done" button. It makes it explicit. The user is done. They are explicitly performing an action (a click) on a "Done" or "Complete".
Of course if you want, you can still return an "Are you sure?" message.
Code:
Private Sub UserForm_QueryClose(Cancel As Integer, _
CloseMode As Integer)
Dim Reply As VbMsgBoxResult
Reply = MsgBox("Do you really want to close this?", vbYesNo)
If Reply = vbYes Then
Cancel = False
Else
MsgBox "OK, let's keep going."
Cancel = True
Exit Sub
End If
End Sub
The user clicks the "X" Close icon.
They get "Do you really want to close this?"
They click "Yes", the userform immediately closes.
They click "No", they get the message "OK, let's keep going." (obviously this can be skipped), and the userform is still there.
Any problems with this? Yes. Suppose you have:
Code:
Sub cmdDone_Click() ' an "Done" button
Unload Me
End Sub
All the above does is cleanly unload the userform. Simple, right?
Except..... what REALLY happens is:
Code:
Sub cmdExit_Click() ' an "Done" button
Unload Me
Call UserForm_QueryClose
End Sub
In other words, the instruction Unload Me executes the QueryClose procedure...which has all those messages. So clicking the "Done" goes through a bunch of instructions you probably do not want. If the commandbutton is explicitly to close the userform, you do not want to mess around with extraneous crap. What to do?
If you DO want the cmdDone to just unload the userform (nothing else) then you have to deal with QueryClose. VBA will execute QueryClose whether you like it or not. So....
add a boolean variable into the mix, like this:
Code:
Option Explicit
Public YeahDoIt As Boolean
Private Sub CommandButton1_Click()
YeahDoIt = True
Unload Me
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, _
CloseMode As Integer)
Dim Reply As VbMsgBoxResult
If YeahDoIt = True Then
Cancel = False
Else
Reply = MsgBox("Do you really want to close this?", vbYesNo)
If Reply = vbYes Then
Cancel = False
Else
MsgBox "OK, let's keep going."
Cancel = True
End If
End If
End Sub
What happens now?
If the user just clicks the "X", QueryClose fires, and does its thing. The boolean YeahDoIt is NOT true, so the previous logic applies. They get the messagebox asking if they are sure. Etc. etc.
If they click the cmdDone button, this sets the boolean YeahDoIt to true, executes QueryClose, which sees YeahDoIt as true....and closes the userform with no messages.
The boolean YeahDoIt is declared as Public....because...Scope, scope, scope. It is used in TWO procedures, thus its Scope must be the entire module...thus Public to that module.
Gerry