Why Does This Code Cause Word to Crash

  • Thread starter Bruce McCormick
  • Start date
B

Bruce McCormick

I have written a macro that collects information from a user, then updates
all the templates within a give folder. The problem is that the macro is
crashing when it tries to save the template. This doesn't happen with every
template. Sometimes it gets through three or four before crashing. I have
pulled my hair out trying to figure out what the problem is. Any
suggestions? (I have indicated the line that is causing the crash below.)
Also, how do you release the frmUserInformationForm variable form?
frmUserInformationForm = Nothing doesn't work.

'===========================================================================
========
' Procedure : UpdateUserInfo
' Author : Bruce McCormick
' Date : 1/6/2004 06:02
' Purpose : Allows the user to update their document templates in one
pass.
' Shortcut : None
' Modified : 1/6/2004 06:02
'===========================================================================
========

Public Sub UpdateUserInfo()

' Declare the variables:
Dim MyUserForm As frmUserInformationForm
Dim sUserName As String
Dim sUserJobTitle As String
Dim sUserDirectPhone As String
Dim sUserFaxPhone As String
Dim sUserEmailAddress As String
Dim sUserDivision As String
Dim sTemplatesPath As String
Dim x As Integer
Dim wdDot As Object

'Collect the user's information via a custom form:
Set MyUserForm = New frmUserInformationForm
MyUserForm.Tag = "Cancel"

'Populate the fields with the current information"
On Error Resume Next
MyUserForm.txtUserName = Application.UserName
MyUserForm.txtUserJobTitle = _
ActiveDocument.CustomDocumentProperties("UserJobTitle")
MyUserForm.txtUserDirectPhone = _
ActiveDocument.CustomDocumentProperties("UserDirectPhone")
MyUserForm.txtUserFaxPhone = _
ActiveDocument.CustomDocumentProperties("UserFaxPhone")
MyUserForm.txtUserEmailAddress = _
ActiveDocument.CustomDocumentProperties("UserEmailAddress")
MyUserForm.cboDivision = _
ActiveDocument.CustomDocumentProperties("UserDivision")

'Show the form:
MyUserForm.Show vbModal

'Save the user information to variables:
If MyUserForm.Tag = "OK" Then 'User pressed OK
sUserName = MyUserForm.txtUserName
sUserJobTitle = MyUserForm.txtUserJobTitle
sUserDirectPhone = MyUserForm.txtUserDirectPhone
sUserFaxPhone = MyUserForm.txtUserFaxPhone
sUserEmailAddress = MyUserForm.txtUserEmailAddress
sUserDivision = MyUserForm.cboDivision.Value
Else
GoTo Shutdown 'User pressed Cancel
End If

'Display a message to the user to be patient:
Application.ScreenRefresh
Dim MyAlertForm As frmBePatient
Set MyAlertForm = New frmBePatient
MyAlertForm.Show vbModeless
MyAlertForm.Repaint

'Insert the variables into each template and update

sTemplatesPath = Options.DefaultFilePath(wdUserTemplatesPath) + "\" + _
sUserDivision + "\"

'Set the user's name in the Tools | Options | User Information dialog
Application.UserName = sUserName

' Save the variables to the DDC template:
SetCustomProperty "UserJobTitle", sUserJobTitle
SetCustomProperty "UserDirectPhone", sUserDirectPhone
SetCustomProperty "UserFaxPhone", sUserFaxPhone
SetCustomProperty "UserEmailAddress", sUserEmailAddress
SetCustomProperty "UserDivision", sUserDivision
ActiveDocument.Close SaveChanges:=wdSaveChanges

'Set the other variables as custom document properties:
'Display a message to the user to be patient:

With Application.FileSearch
.NewSearch
.FileName = "*.dot"
.LookIn = sTemplatesPath
.Execute
For x = 1 To .FoundFiles.Count
Set wdDot = Documents.Open(.FoundFiles(x))

'Add User Job Title:
SetCustomProperty "UserJobTitle", sUserJobTitle

'Add User Direct Phone Number:
SetCustomProperty "UserDirectPhone", sUserDirectPhone

'Add User Fax Phone Number:
SetCustomProperty "UserFaxPhone", sUserFaxPhone

'Add User E-mail Address:
SetCustomProperty "UserEmailAddress", sUserEmailAddress

'Add User Division:
SetCustomProperty "UserDivision", sUserDivision

'Update the document with the new values:
Selection.WholeStory
Selection.Fields.Update
Selection.HomeKey Unit:=wdStory

'Save the document:
' *** This is the line that is causing the crash! ***
Documents(wdDot).Close SaveChanges:=wdSaveChanges

Next
End With

Shutdown:
' Release the variables:
'MyUserForm = Nothing
sUserName = vbNull
sUserJobTitle = vbNull
sUserDirectPhone = vbNull
sUserFaxPhone = vbNull
sUserEmailAddress = vbNull
sUserDivision = vbNull
sTemplatesPath = vbNull
x = vbNull
wdDot = Nothing


End Sub


'===========================================================================
========
' Procedure : SetCustomProperty
' Author : Bruce McCormick
' Date : 1/6/2004 06:38
' Purpose : Checks to see if the CustomDocumentProperty exists in the
Active
' : Document. If yes, and the value is unchanged, it exists the
routine
' : without doing anything. If the value has changed, it updates
the
' : the property to the new value. If the property didn't
previously
' : exits, it creates a property with the new value.
' Shortcut : None
' Modified : 1/6/2004 06:38
'===========================================================================
========

Private Sub SetCustomProperty(sPropertyName As String, sPropertyValue As
String)

' Declare the variables:
Dim oProperty As DocumentProperty
Dim bPropertyExists As Boolean

' See if the CustomDocument Property Exists:
For Each oProperty In ActiveDocument.CustomDocumentProperties
If oProperty.Name = sPropertyName Then

' If yes, set a flag and exit the loop:
' Check to see if the value changed:
If oProperty.Value <> sPropertyValue Then

' If true, delete the value and set the flag to false:
oProperty.Delete
bPropertyExists = False
Else

' Otherwise, set the flag to true
bPropertyExists = True
End If
Exit For
End If

' If no, loop back through:
Next oProperty

' If the CustomDocument Property Does not Exist, add it:
If bPropertyExists = False Then
ActiveDocument.CustomDocumentProperties.Add _
Name:=sPropertyName, _
Type:=msoPropertyTypeString, _
Value:=sPropertyValue, _
LinkToContent:=False
End If

' Release the variables:
bPropertyExists = False

End Sub
 
M

Malcolm Smith

Bruce

There may be a few issues here, but let's deal with one at a time.

The first thing is that you have a pointer called MyUserForm and you have
one pointing to the AlertForm. You create the form objects correctly but
you don't unload them (unless you do that in the code of the form class
itself).

Just make sure that you Unload the forms.

Now, just setting the pointers to Nothing won't close down the form object
all it will do is to orphan the object which is still in memory.

I don't think that this is causing the problem (as I have an idea what is,
but we'll come to that later).

Also when you deal with pointers you Set them to assign them a value as
you have correctly done when you create the object instance. The same
thing when you assign the value Nothing, so you should have written:

Set MyUserForm = Nothing


Now, what is causing the explosion is that the wdDoc is a Document
pointer, as can be seen here:

Set wdDot = Documents.Open(.FoundFiles(x))

Now, what I would do is to declare that as a type Document and not an
Object.

When you come to close the Document, and where it explodes horribly is on
this line here:

Documents(wdDot).Close SaveChanges:=wdSaveChanges

Now wince that wdDot is neither a string or an integer (to reference the
Document in the Documents collection) but an object you have this slightly
wrong.

Try:

wdDot.Close SaveChanges:=wdSaveChanges


And that ought to work.


Does any of this make sense and clarify the matter or have I made it
worse?

Regards
- Malc
www.dragondrop.com
 
B

Bruce McCormick

Malcolm:

First, thanks for the very quick and helpful response. Unfortunately, it is
still crashing.

Here's what I did:

First, I changed the wdDot variable from an object to a document, like this:

Dim wdDot As Document

Next, I changed the use of the variable when closing the template as you
recommended, like this:

wdDot.Close SaveChanges:=wdSaveChanges

I also tried:

ActiveDocument.Close SaveChanges:=wdSaveChanges

Both times it opened the first document, inserted the Custom Document
Properties, saved the document, then crashed.

Do you have any other ideas?

Bruce

P.S. When Word crashes, I run a batch program that
 
B

Bruce McCormick

I forgot: I also unloaded each userform and then set the variable to nothing
, like this:

Unload MyUserForm
Unload MyAlertForm
Set MyUserForm = Nothing
Set MyAlertForm = Nothing
Set wdDot = Nothing
 
B

Bruce McCormick

Malcolm:

Here it is ...

Bruce

'===========================================================================
========
' Procedure : UpdateUserInfo
' Author : Bruce McCormick
' Date : 1/6/2004 06:02
' Purpose : Allows the user to update their document templates in one
pass.
' Shortcut : None
' Modified : 1/8/2004 07:15
'===========================================================================
========

Public Sub UpdateUserInfo()

' Declare the variables:
Dim MyUserForm As frmUserInformationForm
Dim MyAlertForm As frmBePatient
Dim wdDot As Document
Dim sUserName As String
Dim sUserJobTitle As String
Dim sUserDirectPhone As String
Dim sUserFaxPhone As String
Dim sUserEmailAddress As String
Dim sUserDivision As String
Dim sTemplatesPath As String
Dim x As Integer

'Collect the user's information via a custom form:
Set MyUserForm = New frmUserInformationForm
MyUserForm.Tag = "Cancel"

'Populate the fields with the current information"
On Error Resume Next
MyUserForm.txtUserName = Application.UserName
MyUserForm.txtUserJobTitle = _
ActiveDocument.CustomDocumentProperties("UserJobTitle")
MyUserForm.txtUserDirectPhone = _
ActiveDocument.CustomDocumentProperties("UserDirectPhone")
MyUserForm.txtUserFaxPhone = _
ActiveDocument.CustomDocumentProperties("UserFaxPhone")
MyUserForm.txtUserEmailAddress = _
ActiveDocument.CustomDocumentProperties("UserEmailAddress")
MyUserForm.cboDivision = _
ActiveDocument.CustomDocumentProperties("UserDivision")

'Show the form:
MyUserForm.Show vbModal

'Save the user information to variables:
If MyUserForm.Tag = "OK" Then 'User pressed OK
sUserName = MyUserForm.txtUserName
sUserJobTitle = MyUserForm.txtUserJobTitle
sUserDirectPhone = MyUserForm.txtUserDirectPhone
sUserFaxPhone = MyUserForm.txtUserFaxPhone
sUserEmailAddress = MyUserForm.txtUserEmailAddress
sUserDivision = MyUserForm.cboDivision.Value
Else
GoTo Shutdown 'User pressed Cancel
End If

'Display a message to the user to be patient:
Application.ScreenRefresh
Set MyAlertForm = New frmBePatient
MyAlertForm.Show vbModeless
MyAlertForm.Repaint

'Insert the variables into each template and update

sTemplatesPath = Options.DefaultFilePath(wdUserTemplatesPath) + "\" + _
sUserDivision + "\"

'Set the user's name in the Tools | Options | User Information dialog
Application.UserName = sUserName

' Save the variables to the DDC template add-in:
SetCustomProperty "UserJobTitle", sUserJobTitle
SetCustomProperty "UserDirectPhone", sUserDirectPhone
SetCustomProperty "UserFaxPhone", sUserFaxPhone
SetCustomProperty "UserEmailAddress", sUserEmailAddress
SetCustomProperty "UserDivision", sUserDivision
ActiveDocument.Save

'Set the other variables as custom document properties:
'Display a message to the user to be patient:

With Application.FileSearch
.NewSearch
.FileName = "*.dot"
.LookIn = sTemplatesPath
.Execute
For x = 1 To .FoundFiles.Count
Set wdDot = Documents.Open(.FoundFiles(x))

MyAlertForm.Caption = "Updating files ..."
MyAlertForm.lblMessage = "Please wait while we update the " + _
wdDot.Name + " files with your user information."
MyAlertForm.Repaint

'Add User Job Title:
SetCustomProperty "UserJobTitle", sUserJobTitle

'Add User Direct Phone Number:
SetCustomProperty "UserDirectPhone", sUserDirectPhone

'Add User Fax Phone Number:
SetCustomProperty "UserFaxPhone", sUserFaxPhone

'Add User E-mail Address:
SetCustomProperty "UserEmailAddress", sUserEmailAddress

'Add User Division:
SetCustomProperty "UserDivision", sUserDivision

'Update the document with the new values:
Selection.WholeStory
Selection.Fields.Update
Selection.HomeKey Unit:=wdStory

'Save the document:
wdDot.Close SaveChanges:=wdSaveChanges

Next
End With

Shutdown:
' Release the variables:
Unload MyUserForm
Unload MyAlertForm
Set MyUserForm = Nothing
Set MyAlertForm = Nothing
Set wdDot = Nothing
sUserName = vbNull
sUserJobTitle = vbNull
sUserDirectPhone = vbNull
sUserFaxPhone = vbNull
sUserEmailAddress = vbNull
sUserDivision = vbNull
sTemplatesPath = vbNull
x = vbNull

End Sub


'===========================================================================
========
' Procedure : SetCustomProperty
' Author : Bruce McCormick
' Date : 1/6/2004 06:38
' Purpose : Checks to see if the CustomDocumentProperty exists in the
Active
' : Document. If yes, and the value is unchanged, it exists the
routine
' : without doing anything. If the value has changed, it updates
the
' : the property to the new value. If the property didn't
previously
' : exits, it creates a property with the new value.
' Shortcut : None
' Modified : 1/6/2004 06:38
'===========================================================================
========

Private Sub SetCustomProperty(sPropertyName As String, sPropertyValue As
String)

' Declare the variables:
Dim oProperty As DocumentProperty
Dim bPropertyExists As Boolean

' See if the CustomDocument Property Exists:
For Each oProperty In ActiveDocument.CustomDocumentProperties
If oProperty.Name = sPropertyName Then

' If yes, set a flag and exit the loop:
' Check to see if the value changed:
If oProperty.Value <> sPropertyValue Then

' If true, delete the value and set the flag to false:
oProperty.Delete
bPropertyExists = False
Else

' Otherwise, set the flag to true
bPropertyExists = True
End If
Exit For
End If

' If no, loop back through:
Next oProperty

' If the CustomDocument Property Does not Exist, add it:
If bPropertyExists = False Then
ActiveDocument.CustomDocumentProperties.Add _
Name:=sPropertyName, _
Type:=msoPropertyTypeString, _
Value:=sPropertyValue, _
LinkToContent:=False
End If

' Release the variables:
bPropertyExists = False

End Sub
 
M

Malcolm Smith

Just wondered if you are opening the template as a document or a template.
It looks like you are opening it as a document and then saving it as
such.

Is this what you want?

- Malc
 
B

Bruce McCormick

Malcolm:

I wanted to open and save it as a template. How would the code be different?

Bruce
 
M

Malcolm Smith

Ah, right then. I guess then that you may want to open the thing up as a
Template object rather than a Document object (but you may have to test
this yourself) and then when you come to save it, try:


wdDot.SaveAs x, wdFormatTemplate
wdDot.Close SaveChanges:=wdDoNotSaveChanges

Which ought to do what you require.

If this doesn't solve your problem then I can't see it being a million
miles from here.

- Malc
www.dragondrop.com
 

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

Similar Threads

Looping then Va-Boom! 4

Top