Looping then Va-Boom!

B

Bruce McCormick

I hate to post this again. Malcolm Smith graciously attempted to provide
some help, but my code is still blowing up.

I am running the code below in Word XP. It moves through a couple of the
document templates, successfully updates them, then, after a couple of
seconds, crashes. I have tried adding and removing various templates from
the folder, always with the same result.

Why would this get through some templates and then crash?

I am cleaning out my temp files after each crash. Could the templates be
corrupt? What am I doing wrong?

I'd be grateful for any help.

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

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:
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:
ActiveDocument.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
Application.ScreenUpdating = True

End Sub


'===========================================================================
========
' Procedure : SetCustomProperty
' 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/10/2004 15:45
'===========================================================================
========

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
Set oProperty = Nothing

End Sub
 
J

Jezebel

Can't see anything obvious. There's a possible error (although I'd expect an
error message) if the user has changed the data type of an existing document
property. There's no need to update the fields in the document since you are
closing it anyway -- that happens automatically next time you open it.

Here's a simpler way to do set a custom property, that avoids the potential
data type problem:

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

'Delete if present, ignore the error if not
On Error Resume Next
ActiveDocument.CustomDocumentProperties(sPropertyName ).Delete
On Error GoTo 0

'Then add
ActiveDocument.CustomDocumentProperties.Add Name:=sPropertyName, _
LinkToContent:=False, _
Type:=msoPropertyTypeString, _
Value:=sPropertyValue

end sub

If none of this helps, add some diagnostics to find out which line is
causing the crash. One way is to write to a logfile line-by-line.

BTW, there's nothing gained by clearing variables at the end of a routine,
unless they are object variables.
 
B

Bruce McCormick

I hate to show my ignorance, but can you tell me how to write a logfile
routine and use it? Thanks.
 
J

Jezebel

Dim pFileNum as long
pFileNum = freefile
Open "MyLog.txt" for output as #pFileNum
:
Print pFileNum, "Position 1"
:
Close #pFileNum

Then use Notepad to view the file.

Put 'Print' statements at each critical point in your code.
 
B

Bruce McCormick

Okay, I think I solved the problem. First, the templates were not corrupt,
as I feared.

Second, I used the GetObject command to open the documents invisibly to the
user. I was using this statement:

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

But changed to this one:

Set wdDot = GetObject(.FoundFiles(x))

This insures that the the document can be opened invisibly even in Word 97.

Third, it seems that changing a CustomDocumentProperties value doesn't
change the wdDot.Saved value to False. You have to do it explicitly with
this command:

wdDot.Saved = False '<== Note: "wdDot" is the name of the document
object

This insures that Word saves the document

Fourth, I use two statements to save the file then close it, like this:

wdDot.Save
wdDot.Close SaveChanges:=wdDoNotSaveChanges

If you try to condense this to one statement (as below), Word will ask the
user to confirm that he wants to save the template. I'm not sure why. There
may be a way to turn this off and use one line. I couldn't find any
documentation.

wdDot.Close SaveChanges:=wdSaveChanges

I am reposting the working code below: I'm not exactly sure wht the previous
code didn't work. But, this does. Aw, the mystery of programming!

'====================================================
' Procedure : UpdateUserInfo
' Date : 1/6/2004 06:02
' Purpose : Allows the user to update their document templates in one
pass.
' Shortcut : None
' Modified : 1/10/2004 15:08
'====================================================
Public Sub UpdateUserInfo()

' Declare the variables:
Dim MyUserForm As frmUserInformationForm
Dim MyAlertForm As frmBePatient
Dim wdDot As Document
Dim sStatusBarMsg As String
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
Application.ScreenUpdating = False

'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:
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 = GetObject(.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

'Save the document:
wdDot.Saved = False
'wdDot.Close SaveChanges:=wdSaveChanges
wdDot.Save
wdDot.Close SaveChanges:=wdDoNotSaveChanges

'Close SaveChanges:=True
'wdDot.SaveAs wdFormatTemplate
'wdDot.Save
'wdDot.Close SaveChanges:=wdDoNotSaveChanges
'ActiveDocument.Close SaveChanges:=wdSaveChanges

Next
End With

Shutdown:
' Release the variables:
Unload MyUserForm
Unload MyAlertForm
Set MyUserForm = Nothing
Set MyAlertForm = Nothing
Set wdDot = Nothing
Application.ScreenUpdating = True

End Sub


'====================================================
' Procedure : SetCustomProperty
' 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/10/2004 15:45
'====================================================

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
Else
bPropertyExists = False
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
Set oProperty = Nothing

End Sub
 

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


Top