Checking if the bookmarks are still there in order to get the form to work

J

jab

Hi

I have created a userform that bring up the content from certain
bookmarks in the document and presents them in the fields of the form.
The user changes these settings and the new content of the bookmarks
are cascaded throughout the documents headers and footers (and in text)
via ref fields.

The bookmarks themselves is hidden in the header of the first page of
the document in a textbox that is hidden behind some header graphics.
This to make it as hard as possible to accidentally delete them.
Everything works fine but if the bookmarks despite these efforts have
been deleted by the users, we get a "5941" runtime error.

Can someone please help me write code that checks if the bookmarks are
still there, if there not (any of them) recreates them in the same
fashion / or a better fashion?

NOTE the current bookmarks of the templates can right now not be
reached via Edit/goto bookmarks. One needs first to go into the headers
of the docs and into a textbox within them to be able to reach them via
that command in word. Here is the code for the form/bookmark:

Option Explicit

Private Sub UserForm_Initialize()

Dim project As String
Dim Clientname As String
Dim DocumentType As String
Dim Author As String
Dim prefdate As String

project = ActiveDocument.Bookmarks("Project").Range.Text
TxtProject.Text = project

Clientname = ActiveDocument.Bookmarks("clientname").Range.Text
TxtClient.Text = Clientname

DocumentType = ActiveDocument.Bookmarks("documenttype").Range.Text
TxtDocumentType.Text = DocumentType

Author = ActiveDocument.Bookmarks("author").Range.Text
txtAuthor.Text = Author

prefdate = ActiveDocument.Bookmarks("prefdate").Range.Text
Txtprefdate.Text = prefdate

End Sub

Private Sub cmdCancel_Click()

Selection.GoTo What:=wdGoToBookmark, Name:="goback"

FrmDocProp.Hide
Unload FrmDocProp
Exit Sub
End Sub

Private Sub CmdOK_Click()

Dim vProject As String
Dim vClient As String
Dim vDocType As String
Dim vAuthor As String
Dim vprefdate As String

vProject = FrmDocProp.TxtProject.Text
vClient = FrmDocProp.TxtClient.Text
vDocType = FrmDocProp.TxtDocumentType.Text
vAuthor = FrmDocProp.txtAuthor.Text
vprefdate = FrmDocProp.Txtprefdate.Text

'declare a range
Dim bkProjectRange As Range
Dim bkClientRange As Range
Dim bkDocTypeRange As Range
Dim bkAuthorRange As Range
Dim bkPrefdateRange As Range

'set the range equal to your current bookmark
Set bkClientRange = ActiveDocument.Bookmarks("Clientname").Range
Set bkProjectRange = ActiveDocument.Bookmarks("Project").Range
Set bkDocTypeRange = ActiveDocument.Bookmarks("DocumentType").Range
Set bkAuthorRange = ActiveDocument.Bookmarks("Author").Range
Set bkPrefdateRange = ActiveDocument.Bookmarks("Prefdate").Range

'pass in the info now contained in the variable (what the user
typed)
bkProjectRange.Text = vProject
bkClientRange.Text = vClient
bkDocTypeRange.Text = vDocType
bkAuthorRange.Text = vAuthor
bkPrefdateRange.Text = vprefdate

'wrap the same bookmark around this text
ActiveDocument.Bookmarks.Add "ClientName", bkClientRange
ActiveDocument.Bookmarks.Add "Project", bkProjectRange
ActiveDocument.Bookmarks.Add "DocumentType", bkDocTypeRange
ActiveDocument.Bookmarks.Add "Author", bkAuthorRange
ActiveDocument.Bookmarks.Add "Prefdate", bkPrefdateRange
 
G

Greg

jab,

First I would abandon the tuck-away bookmarks and use Variables and
DOCVARIABLE fields instead.

Try:
Option Explicit
Dim oVar As Variables
Private Sub UserForm_Initialize()
On Error GoTo Handler
Set oVar = ActiveDocument.Variables
Me.TxtProject.Text = oVar("Project").Value
Me.TxtClient.Text = oVar("Client").Value
Me.TxtDocumentType.Text = oVar("DocType").Value
Me.TxtAuthor.Text = oVar("DocAuthor").Value
Me.Txtprefdate.Text = oVar("PrefDate").Value
Exit Sub
Handler:
oVar("Project").Value = "New value"
oVar("Client").Value = "New value"
oVar("DocType").Value = "New value"
oVar("DocAuthor").Value = "New value"
oVar("PrefDate").Value = "New value"
Resume
End Sub
Private Sub cmdCancel_Click()
Me.Hide
End Sub
Private Sub CmdOK_Click()
Set oVar = ActiveDocument.Variables
oVar("Project").Value = Me.TxtProject.Text
oVar("Client").Value = Me.TxtClient.Text
oVar("DocType").Value = Me.TxtDocumentType.Text
oVar("DocAuthor").Value = Me.TxtAuthor.Text
oVar("PrefDate").Value = Me.Txtprefdate.Text
ActiveDocument.Fields.Update
Me.Hide
End Sub

Then in place of REF fields to the bookmarks, use DOCVARIABLE fields
(e.g., {DOCVARIABLE "Project"}

HTH
 
D

Dave Lett

Hi jab,

I agree with Greg that you might consider other tools so that you don't
actually have to write to the document each time. You simply update a field.
The problem with this method is that users are users. If they can delete a
bookmark, then they can delete a field. With the bookmark method, at least
you KNOW that your insert point (i.e., the bookmark) has been deleted.
Therefore, you can create a quick function to check if your bookmark exists
or not. Have a look at the following as a potential start:

Private Sub UserForm_Initialize()

Dim project As String
Dim Clientname As String
Dim DocumentType As String
Dim Author As String
Dim prefdate As String

If fChkCreateBkmk Then
project = ActiveDocument.Bookmarks("Project").Range.Text
TxtProject.Text = project

Clientname = ActiveDocument.Bookmarks("clientname").Range.Text
TxtClient.Text = Clientname

DocumentType = ActiveDocument.Bookmarks("documenttype").Range.Text
TxtDocumentType.Text = DocumentType

Author = ActiveDocument.Bookmarks("author").Range.Text
txtAuthor.Text = Author

prefdate = ActiveDocument.Bookmarks("prefdate").Range.Text
Txtprefdate.Text = prefdate
End If
End Sub

Public Function fChkCreateBkmk() As Boolean
Dim aBkNames As Variant
Dim lCount As Long
Dim err_Handler
Dim sMsg As String

On Error GoTo err_Handler

sMsg = "fChkCreateBkmk"
fChkCreateBkmk = False

'''aBkNames = Array("Project", "clientname", "documenttype", "author",
"prefdate")
For lCount = 0 To UBound(aBkNames)
If ActiveDocument.Bookmarks.Exists(Name:=aBkNames(lCount)) Then
''do nothing, the bookmark is there
Else
''we're not going to exit the function here,
''remember the value for fChkCreateBkmk doesn't
''become True until all the bookmarks are checked
''or created; therefore, when we get a false, we'll just
''create the bookmark
Select Case lCount
Case 0 ''Project
''in each case, you'll need to
''develop the routine to reinsert
''the bookmark at the appropriate
''position in the document
Case 1 ''clientname

Case 2 ''documenttype

Case 3 ''author

Case 4 ''prefdate

End Select
End If
Next lCount

'' once we get here, all the bookmarks have been checked,
'' and if missing, then created therefore the next line is
fChkCreateBkmk = True
''you exit the function here; otherwise the routine will
''run through the err_Handler
Exit Function

''this err_Handler will only be activated if there is some type
''of error in the code.
err_Handler:
fChkCreateBkmk = False
MsgBox sMsg & " failed." & vbCr & _
Err.Number & vbTab & _
Err.Description, vbInformation
End Function

HTH,
Dave
 
G

Greg

Dave,

Nice bit of code, but the OP already said that he/she populated REF
fields based on his tuck away bookmarks. Users can delete REF or
DOCVARIABLE fields indiscrimately. I don't see any advantage with
staying with the bookmarks. Maybe I am missing something.

P.S. If you get a chance, go back to your reply on the VBA nested IF
field thread. Hoping you can explain the odd wildcard behaviour.
 
D

Dave Lett

Greg,
Yes, yes, yes. You're right. If the user can delete anything, then it's more
efficient Variables. While not impossible to delete, it would take a very
savvy user. Therefore, checking to see if they exist isn't a step you'd
really NEED to take, as you would with bookmarks.

Dave

P.S. I will double check the VBA nested IF field thread.
 
D

Doug Robbins - Word MVP

The other thing, if the docvariable field is inadvertently deleted, the user
can always reinsert the docvariable field and it will display the data
without any code having to be run. If the bookmark isn't there, the whole
thing falls over.

I probably should update the userform item on the word.mvps website to use
docvariables instead of bookmarks, but everytime I start, I keep on
enhancing it and it becomes a major project and I give it away. One day
maybe.

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

jab

By using my initial BookMark method I'm able to bring up the text
already in the bookmarks and display them in the dialog. That is
something that I do not know how to do with the docvariable method. Can
one do that Greg?
Also: When it comes to updating the content of Headers and Footers that
contains fields...I have managed to do that and the REF fields for
bookmarks gets updated but not the docvarialble ones? (Below is my
"Update fileds in headers and footers" code.

I have an error code in place that seemes to work and that recreates
the bookmarks (once again Tucked away under the Graphic in the headers)
if one of them is missing. That code is also below. I'm not pleased
with it (mostly because word jumps into Printview mode and the screen
flickers quite alot while the missing bookmarks are recreated) and I
will try Daves method with the case method.

Thanx guys!
 
J

jab

Sorry guys! Forgot the code.

Updating fields in headers and footers of the document:

Dim sect As Section
Dim head As HeaderFooter
Dim foot As HeaderFooter
Dim del As Range
Dim flt As Field
Dim sectcount As Integer
Dim sectloop As Integer


For Each del In ActiveDocument.StoryRanges
For Each flt In del.Fields
If flt.Type = wdFieldRef Then
flt.Update
End If
Next
Next
sectcount = ActiveDocument.Sections.Count
For sectloop = 1 To sectcount
Set sect = ActiveDocument.Sections(sectloop)
For Each head In sect.Headers
For Each flt In head.Range.Fields
If flt.Type = wdFieldRef Then
flt.Update
End If
Next
Next
Next

For Each del In ActiveDocument.StoryRanges
For Each flt In del.Fields
If flt.Type = wdFieldRef Then
flt.Update
End If
Next
Next
sectcount = ActiveDocument.Sections.Count
For sectloop = 1 To sectcount
Set sect = ActiveDocument.Sections(sectloop)
For Each foot In sect.Footers
For Each flt In foot.Range.Fields
If flt.Type = wdFieldRef Then
flt.Update
End If
Next
Next
Next

Unload Me
End
End Sub

Code for error handling of bookmarks

Private Sub UserForm_Initialize()

Dim projname As String
Dim Clientname As String
Dim doctype As String
Dim prefdate As String
'Dim Author As String
Dim contactp As String
Dim dirphonenumber As String
Dim mobile As String
Dim email As String
Dim check As Boolean

check = True

On Error GoTo Nobookmarks


projname = ActiveDocument.Bookmarks("projname").Range.Text
txtprojname.Text = projname

Clientname = ActiveDocument.Bookmarks("clientname").Range.Text
Txtclientname.Text = Clientname

doctype = ActiveDocument.Bookmarks("doctype").Range.Text
txtDocutype.Text = doctype

prefdate = ActiveDocument.Bookmarks("prefdate").Range.Text
txtdate.Text = prefdate

'Author = ActiveDocument.Bookmarks("author").Range.Text
'txtauthorn.Text = Author

contactp = ActiveDocument.Bookmarks("contactp").Range.Text
txtcontactp.Text = contactp

dirphonenumber = ActiveDocument.Bookmarks("dirphonenumber").Range.Text
txtdirphonenumber.Text = dirphonenumber

mobile = ActiveDocument.Bookmarks("mobile").Range.Text
Txtmobil.Text = mobile

email = ActiveDocument.Bookmarks("email").Range.Text
txtemail.Text = email

check = False

Nobookmarks:
If check Then

Dim newTextbox As Shape

Selection.HomeKey Unit:=wdStory
If ActiveWindow.View.SplitSpecial <> wdPaneNone Then
ActiveWindow.Panes(2).Close
End If
If ActiveWindow.ActivePane.View.Type = wdNormalView Or
ActiveWindow. _
ActivePane.View.Type = wdOutlineView Then
ActiveWindow.ActivePane.View.Type = wdPrintView
End If
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
Selection.MoveDown Unit:=wdLine, Count:=1

' add a new text box

Set newTextbox =
ActiveDocument.Sections(1).Headers(wdHeaderFooterFirstPage).Shapes.AddTextbox
_
(Orientation:=msoTextOrientationHorizontal, _
Left:=340.55, Top:=30, Width:=190, Height:=25)

'Add text to the text box

newTextbox.TextFrame.TextRange.Select
Selection.Bookmarks.Add ("projname")
Selection.TypeText Text:=" "
Selection.EndKey
Selection.Bookmarks.Add ("prefdate")
Selection.TypeText Text:=" "
Selection.EndKey
Selection.Bookmarks.Add ("doctype")
Selection.TypeText Text:=" "
Selection.EndKey
Selection.Bookmarks.Add ("clientname")

newTextbox.Fill.Solid
newTextbox.Fill.Visible = msoFalse
newTextbox.Fill.Transparency = 0#
newTextbox.Line.Transparency = 0#
newTextbox.Line.Visible = msoFalse
newTextbox.LockAspectRatio = msoFalse
newTextbox.WrapFormat.AllowOverlap = True
newTextbox.WrapFormat.Side = wdWrapBoth
newTextbox.WrapFormat.DistanceTop = InchesToPoints(0)
newTextbox.WrapFormat.DistanceBottom = InchesToPoints(0)
newTextbox.WrapFormat.DistanceLeft = InchesToPoints(0.13)
newTextbox.WrapFormat.DistanceRight = InchesToPoints(0.13)
newTextbox.WrapFormat.Type = 3
newTextbox.TextFrame.AutoSize = False
newTextbox.TextFrame.WordWrap = False
newTextbox.Select
newTextbox.ZOrder (msoSendToBack)
newTextbox.ZOrder (msoSendBehindText)


ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
Selection.GoTo What:=wdGoToBookmark, Name:="GoBack"

Resume Next

Else: Resume Next
End If

End Sub
 
C

Charles Kenyon

You are checking for REF fields but not docvariable fields and so, no, the
docvariable fields will not update.
Check for both. I'm not sure of the constant for docvariable fields but
suspect it is wdFieldDocVariable.


--
Charles Kenyon

Word New User FAQ & Web Directory: http://addbalance.com/word

Intermediate User's Guide to Microsoft Word (supplemented version of
Microsoft's Legal Users' Guide) http://addbalance.com/usersguide


--------- --------- --------- --------- --------- ---------
This message is posted to a newsgroup. Please post replies
and questions to the newsgroup so that others can learn
from my ignorance and your wisdom.
 
D

Doug Robbins - Word MVP

Why not just use

head.Range.Fields.Update

That will update all of the fields in the header.

To get the value back out of a docvariable field, use the following syntax:

Private Sub UserForm_Initialize()
With ActiveDocument
txtCompany = .Variables("Company").Value
txtProject = .Variables("Project").Value
txtDocNum = .Variables("DocNum").Value
txtRevNum = .Variables("Revision").Value
txtDocTitle = .Variables("DocTitle").Value
End With
txtDocNum.SetFocus
End Sub

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

jab

Thanx once again guys!

The docvariable method worx fine. I have protected the areas with the
reffields in the doc and has set the default setting for word on our
office computers to show fields as shaded. That combined with the
information to NOT delete any shaded areas should do it.

/Jan Åberg Sweden
 
J

jab

One last question. Is there any way to in the custom dialog alter the
txt fields to be a "mailto" field thus displaying the docvariable ref
field in the document as a clickble mailto field?
 
D

Doug Robbins - Word MVP

If you use the following construction in the document

{ HYPERLINK "mailto:{ DOCVARIABLE varname }" }

and varname contains a valid email address, you will get

mailto: (e-mail address removed)

on which you will be able to use Ctrl+Left Click.

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