MS Office Forum / Word / Programming / February 2007
Variable Values Disappears...
|
|
Thread rating:  |
jab@consignit.se - 29 Jan 2007 13:20 GMT Hi all
I have made a custom Dialog in which users will enter information. This information will then be downloaded into the document via docvariables. Some of the values shall also be saved as custom properties with the document
I want the dialog to have preset values if no values are present in the document i.e NOT in the document show the message "Error, No document variable supplied" but a predefiend value via VBA instead. If entries priviously have been made those should be loeded into the dialog text fields when it is opened.
The code so far works and displays everything as stated if ALL the fields of the dialog are prefilled in the dot file or if the user fills them all in. But if one field is left empty when clicking ok in the dialog, the variable entry in the document shows the error statement described above in the docuument variable field (I want the default value to be there). AND, here's the weirdest part, when opening the dialog again for reentry of information, not only the left out field is empty but a few of the others as well, i.e the code does not pick up the values of the variables in the document and presents them as the're supposed to. It only does so if ALLthe fields are filled in and the values transferred to the document
Could som1 please tell me what is going on?
Here is the code:
Option Explicit Dim oVar As Variables Dim objCustomProperties As DocumentProperties Private Sub UserForm_Initialize()
On Error GoTo Handler Set oVar = ActiveDocument.Variables ' ## JAB Added ref to custom doc properties Set objCustomProperties = ActiveDocument.CustomDocumentProperties
Me.txtprojname.Text = oVar("Project").Value Me.Txtclientname.Text = oVar("Client").Value Me.txtDocutype.Text = oVar("DocType").Value Me.txtdate.Text = oVar("PrefDate").Value Me.txtcontactp.Text = oVar("Contact").Value Me.txtdirphonenumber.Text = oVar("DirPhone").Value Me.Txtmobil.Text = oVar("Mobil").Value Me.txtemail.Text = oVar("email").Value Me.Txtnameofauthor.Text = oVar("DocAuthor").Value Me.txtfax.Text = oVar("fax").Value Me.txtstad.Text = oVar("City").Value Me.txtpostal.Text = oVar("Postalnr").Value Me.txtstreet.Text = oVar("street").Value
Exit Sub
With ActiveDocument txtprojname = .Variables("Project").Value Txtclientname = .Variables("Client").Value txtDocutype = .Variables("Doctype").Value txtdate = .Variables("Prefdate").Value txtcontactp = .Variables("Contact").Value txtdirphonenumber = .Variables("Dirphone").Value Txtmobil = .Variables("Mobil").Value txtemail = .Variables("email").Value Txtnameofauthor = .Variables("DocAuthor").Value txtfax = .Variables("fax").Value txtstad = .Variables("City").Value txtpostal = .Variables("Postalnr").Value txtstreet = .Variables("Street").Value
End With
txtprojname.SetFocus Txtclientname.SetFocus txtDocutype.SetFocus txtdate.SetFocus txtcontactp.SetFocus txtdirphonenumber.SetFocus Txtmobil.SetFocus txtemail.SetFocus Txtnameofauthor.SetFocus txtfax.SetFocus txtstad.SetFocus txtpostal.SetFocus txtstreet.SetFocus
Handler: oVar("Project").Value = "Project name" oVar("Client").Value = "Client Name" oVar("DocType").Value = "Type of Document" oVar("PrefDate").Value = "Last editing date of document" oVar("Contact").Value = "Contact person name at " oVar("dirphone").Value = " " oVar("mobil").Value = " " oVar("email").Value = "...@" oVar("DocAuthor").Value = "Name of document responsible" oVar("fax").Value = " " oVar("city").Value = " " oVar("postalnr").Value = " " oVar("street").Value = " "
End Sub
Private Sub cmdCancel_Click() If ActiveDocument.ProtectionType = wdNoProtection Then ActiveDocument.Protect Type:=wdAllowOnlyFormFields, NoReset:=True, Password:=""
End If
If ActiveDocument.ProtectionType = wdAllowOnlyFormFields = True Then ActiveDocument.Unprotect Password:=""
Else
If ActiveDocument.ProtectionType = wdNoProtection Then ActiveDocument.Protect Type:=wdAllowOnlyFormFields, NoReset:=True, Password:="" Else ActiveDocument.Unprotect Password:=""
End If End If ActiveDocument.Protect Type:=wdAllowOnlyFormFields, NoReset:=True, Password:="" Unload Me End
End Sub
Private Function CheckExistsCDP(CDPName As String, propcoll As Object) As Boolean Dim PrCust As Object For Each PrCust In propcoll If PrCust.Name = CDPName Then CheckExistsCDP = True Exit For Else CheckExistsCDP = False End If Next End Function
Private Sub CmdOK_Click()
Set oVar = ActiveDocument.Variables Set objCustomProperties = ActiveDocument.CustomDocumentProperties
If Not CheckExistsCDP("Project", objCustomProperties) Then objCustomProperties.Add Name:="Project", LinkToContent:=False, Type:=msoPropertyTypeString, Value:=Me.txtprojname.Text Else objCustomProperties("Project").Value = Me.txtprojname.Text End If
If Not CheckExistsCDP("Client", objCustomProperties) Then objCustomProperties.Add Name:="Client", LinkToContent:=False, Type:=msoPropertyTypeString, Value:=Me.Txtclientname.Text Else objCustomProperties("Client").Value = Me.Txtclientname.Text End If
'If Not CheckExistsCDP("Contact", objCustomProperties) Then ' objCustomProperties.Add Name:="Contact", LinkToContent:=False, Type:=msoPropertyTypeString, Value:=Me.txtcontactp.Text 'Else ' objCustomProperties("Contact").Value = Me.txtcontactp.Text 'End If
If Not CheckExistsCDP("DocType", objCustomProperties) Then objCustomProperties.Add Name:="DocType", LinkToContent:=False, Type:=msoPropertyTypeString, Value:=Me.txtDocutype.Text Else objCustomProperties("DocType").Value = Me.txtDocutype.Text End If
If Not CheckExistsCDP("DocAuthor", objCustomProperties) Then objCustomProperties.Add Name:="DocAuthor", LinkToContent:=False, Type:=msoPropertyTypeString, Value:=Me.Txtnameofauthor.Text Else objCustomProperties("DocAuthor").Value = Me.Txtnameofauthor.Text End If
'If Not CheckExistsCDP("fax", objCustomProperties) Then ' objCustomProperties.Add Name:="fax", LinkToContent:=False, Type:=msoPropertyTypeString, Value:=Me.txtfax.Text 'Else ' objCustomProperties("fax").Value = Me.txtfax.Text 'End If
'If Not CheckExistsCDP("city", objCustomProperties) Then ' objCustomProperties.Add Name:="city", LinkToContent:=False, Type:=msoPropertyTypeString, Value:=Me.txtstad.Text 'Else ' objCustomProperties("city").Value = Me.txtstad.Text 'End If
'If Not CheckExistsCDP("postalnr", objCustomProperties) Then ' objCustomProperties.Add Name:="postalnr", LinkToContent:=False, Type:=msoPropertyTypeString, Value:=Me.txtpostal.Text 'Else ' objCustomProperties("postalnr").Value = Me.txtpostal.Text 'End If
'If Not CheckExistsCDP("street", objCustomProperties) Then ' objCustomProperties.Add Name:="street", LinkToContent:=False, Type:=msoPropertyTypeString, Value:=Me.txtstreet.Text 'Else ' objCustomProperties("street").Value = Me.txtstreet.Text 'End If
oVar("DocType").Value = Me.txtDocutype.Text oVar("Project").Value = Me.txtprojname.Text oVar("Client").Value = Me.Txtclientname.Text oVar("PrefDate").Value = Me.txtdate.Text oVar("Contact").Value = Me.txtcontactp.Text oVar("Dirphone").Value = Me.txtdirphonenumber.Text oVar("mobil").Value = Me.Txtmobil.Text oVar("email").Value = Me.txtemail.Text oVar("DocAuthor").Value = Me.Txtnameofauthor.Text oVar("fax").Value = Me.txtfax.Text oVar("City").Value = Me.txtstad.Text oVar("postalnr").Value = Me.txtpostal.Text oVar("street").Value = Me.txtstreet.Text
Jay Freedman - 29 Jan 2007 15:18 GMT The easiest solution, I think, is to define all the document variables _in the template_ to contain at least a space character. Then each document based on the template will automatically start with all the variables defined. (Setting a document variable's value to the empty string "" deletes the variable.) That will prevent error messages in the DocVariable fields.
The reason you're seeing empty fields in your dialog is that the first time the Userform_Initialize procedure tries to retrieve a value for an undefined docvariable, the On Error trap sends execution immediately to the Handler label. That error handler then defines all the docvariables, but it never branches back to the beginning of the procedure to load the rest of the fields in the userform. So an alternative would be to place a label (something like StartAgain) just after the Set objCustomProperties statement. Then, at the bottom of the error handler, add the lines
Err.Clear GoTo StartAgain
As a separate issue, everything between the Exit Sub statement and the Handler label should be removed. I assume those were just some things you tried for debugging, but now it's dead (unreachable) code because of the Exit Sub statement. The declaration and setting of objCustomProperties can also be removed from Userform_Initialize, because that object isn't used in that procedure -- it's used only in CmdOK_Click.
 Signature Regards, Jay Freedman Microsoft Word MVP FAQ: http://word.mvps.org Email cannot be acknowledged; please post all follow-ups to the newsgroup so all may benefit.
> Hi all > [quoted text clipped - 220 lines] > oVar("postalnr").Value = Me.txtpostal.Text > oVar("street").Value = Me.txtstreet.Text jab@consignit.se - 29 Jan 2007 16:02 GMT Thanx a bunch Jay for your swift answer. I will try this tomorrow. Signing off for today. I didn't even see the exit sub statement. Must have been left there by mistake at some point. Boy one gets blind sometimes
I will come back tomorrow and tellyou how it went
Kind Regards
Jan
Jay Freedman - 29 Jan 2007 16:51 GMT Hi Jan,
I hope you see this before you get too frustrated...
You do need the Exit Sub statement, between the code that should be executed and the error handler. If it's omitted, the error handler will execute every time the code runs -- not what you want. Besides that, if you include the GoTo to send execution back to the top of the procedure when an error occurs, but omit the Exit Sub, then you'll get into an infinite loop.
 Signature Regards, Jay Freedman Microsoft Word MVP FAQ: http://word.mvps.org Email cannot be acknowledged; please post all follow-ups to the newsgroup so all may benefit.
> Thanx a bunch Jay for your swift answer. I will try this tomorrow. > Signing off for today. I didn't even see the exit sub statement. Must [quoted text clipped - 6 lines] > > Jan jab@consignit.se - 31 Jan 2007 10:56 GMT Hi Jay
Maybe I haven't done the changes you suggested in the correct way but I think so...How does write the StartAgain lable..."StartAgain:" right?
I still get the Error message in the document saying "Error! No document variable supplied." when a value is not supplied in the dialog. I want the the preset value in the handler to show when when that value is left out by the user. Also, now, if ONE value is left out ALL of the preset values for the different txtfields in the VBA handler code fills the dialog fields if one bring up the dialog again and not just the one field left out.
This is how I want it to work. If the user decides to not fill in one of the fields that field will still be populated with something (like a space character as you suggested) thus preventing the error message to appear in the document.
If the above has been done and the user brings up the dialog again, all the variable values that contains the users priviously added information, shall populate the fields in the dialog and NOT the handler codes preset values.
I have to somhow controle what field(s) has been left empty and populate that field(s) with a default value (like space). The other fields in the document that contains the priviously user defined values must populate the dialogs txtfileds when/if the users brings up the dialog again.
Maybe a controle making sure that the user cannot leave a field completely empty...better solution whould be that the code fills an empty/left out field with a space. Please assist me futher.
Kind Regards Jan
Jay Freedman - 31 Jan 2007 16:22 GMT Hi Jan,
Sorry, I didn't sufficiently analyze what your error handler was doing. The handler should not set all the defaults at once when there's only one (or more) nonexistent document variable. The better solution is to make a separate subroutine that's called once for each document variable; that subroutine will contain the error handler, which will set the proper default value only for that variable.
Similarly, you should have a subroutine that is called once to transfer each text box value to the document. If the text box value is an empty string because the user deliberately left it empty, the corresponding document variable (and custom document property) will be set to a single space character.
This is the code I recommend. I've shown calls for only the Project and Client variables, but I think you'll see what is needed for the others.
Private Sub cmdCancel_Click() Unload Me End Sub '-------- Private Sub cmdOK_Click() FillDocVariable tBox:=txtprojname, _ docVar:="Project", docProp:="Project" FillDocVariable tBox:=txtclientname, _ docVar:="Client", docProp:="Client" ActiveDocument.Fields.Update Unload Me End Sub '-------- Private Sub UserForm_Initialize() InitializeTextBox tBox:=txtprojname, _ docVar:="Project", defaultVal:="Project name" InitializeTextBox tBox:=txtclientname, _ docVar:="Client", defaultVal:="Client name" End Sub '-------- Private Sub InitializeTextBox(tBox As TextBox, _ docVar As String, defaultVal As String)
Dim tmp As String On Error GoTo Handler
tmp = ActiveDocument.Variables(docVar).Value If Trim(tmp) <> "" Then tBox.Text = tmp Else ' value is one or more space characters tBox.Text = "" End If Exit Sub
Handler: tBox.Text = defaultVal End Sub '-------- Private Sub FillDocVariable(tBox As TextBox, _ docVar As String, docProp As String)
If Trim(tBox.Text) <> "" Then ActiveDocument.Variables(docVar).Value = tBox.Text Else ' value is one or more space characters ActiveDocument.Variables(docVar).Value = " " End If
If CheckExistsCDP(CDPName:=docProp) Then ActiveDocument.CustomDocumentProperties(docProp).Value = _ ActiveDocument.Variables(docVar).Value Else ActiveDocument.CustomDocumentProperties.Add _ Name:=docProp, LinkToContent:=False, _ Type:=msoPropertyTypeString, _ Value:=ActiveDocument.Variables(docVar).Value End If End Sub '-------- Private Function CheckExistsCDP(CDPName As String) As Boolean Dim PrCust As DocumentProperty CheckExistsCDP = False For Each PrCust In ActiveDocument.CustomDocumentProperties If LCase(PrCust.Name) = LCase(CDPName) Then CheckExistsCDP = True Exit For End If Next End Function
While you're looking at this, notice that I've simplified the cmdCancel_Click and CheckExistsCDP code. For the cancel button, you had a lot of unprotecting and reprotecting for forms, accomplishing nothing that I could see. For CheckExistsCDP , it's more efficient to set the return value to False once, and then change it to True only if the property is found. Also, when comparing strings, you should make sure their cases are the same.
 Signature Regards, Jay Freedman Microsoft Word MVP FAQ: http://word.mvps.org Email cannot be acknowledged; please post all follow-ups to the newsgroup so all may benefit.
> Hi Jay > [quoted text clipped - 32 lines] > > Kind Regards Jan jab@consignit.se - 02 Feb 2007 17:19 GMT Hi Jay
It all works like a dream now thanks to you.
The reason for the protect unprotect thing is that the area where the variables are supposed to go in is protected to prevent users from accidentally delete the variable placeholders. I guess I could skip the noreset parts due to that I'm no longer using formfields.
Thnx again. I will definately study some more VBA!
Kind Regards
Jan
|
|
|