A real bookmark is a defined (named)
range. It is not a field.
A formfield is a
field that also has a defined range. Therefore it is ALSO a member of the Bookmark collection. It is primarily a member of the Formfields collection.
In other words, formfields are always (also) bookmarks.
Bookmarks are not always (also) formfields.
For example, one of the things I have always found a little annoying is identifying and accessing a specific table in a document
no matter where it is.
So I regularly bookmark my tables. I select the table and go Insert > Bookmark and give it a name, say "Clients". Now, this does not directly name the table, but it effectively does. I can create a table object and set it for THAT table...no matter where it is. The table can be moved, or other tables created before...it does not matter.
Let me back up.
Say you have a table. It is the first table in the document. It is identified as:
ActiveDocument.Tables(1)
It is identified in the Tables collection by its index number. The index number is set by the order in the document.
If you create a table before it, it
automatically becomes:
ActiveDocument.Tables(2)
In other words, the index number of a table is NOT directly tied to the table itself.
BUT, if you bookmark it, no matter where it is, no matter how many tables you create before it, you can always point to it
by name with a table object.
Code:
Dim oTable As Table
Set oTable = ActiveDocument.Bookmarks("Client") _
.Range.Tables(1)
oTable is now the table IN the bookmark, regardless of where it is in the document. This is because Bookmarks are dynamic.
Bookmarks are
locations. Their critical properties are .Start and .End. They give a name to a location that starts
here and ends
there. By being dynamic, if you put something new between Start and End, those parameters adjust accordingly.
So if the purpose is to put something AT a specific location, use bookmarks.
Formfields are fields. Now they do have specific locations, so they are also bookmarks. However, their main purpose is to
take user input.
Further, for formfields to function as intended, the document must be protected for forms.
Bookmarks do not.
Further, bookmarks can be
nested.
In the above example, say the whole table was bookmarked as "Client", and within it, Cell(2, 3) was bookmarked as "IBM".
Without ever identifying the table, you could get the contents of THAT cell.
Code:
Msgbox ActiveDocument.Bookmarks("IBM").Range.Text
or write to THAT cell:
Code:
ActiveDocument.Bookmarks("IBM").Range.Text = _
"Honking big company"
or make a Cell object, and have access to all the properties of a Cell object:
Code:
Dim oCell As Cell
Set oCell = ActiveDocument.Bookmarks("IBM").Range.Cells(1)
oCell.Shading.Texture = wdTexture15Percent
So say, THAT cell was originally Cell(2, 3) of the table. You add four rows above it. By index number it is now Cell(6, 3). However, if it is bookmarked...it does not matter!
Code:
Dim oCell As Cell
Set oCell = ActiveDocument.Bookmarks("IBM").Range.Cells(1)
will still make a cell object of THAT cell, regardless of its index numbers within the table.
Bookmarks, in a sense, are the highest level of location parameters. They even work across Story ranges, because VBA accesses them via the Bookmark collection. Say you bookmark the Header of Section 1, naming it "Section1Primary":
Code:
Dim r As Range
Set r = ActiveDocument.Bookmarks("Section1Primary").Range
r.Text = "Yadda yadda"
badda bing, badda boom. Section 1 header is "Yadda yadda".
Note to other Word people, yes, yes, there are other ways of doing the same thing, like with a HeaderFooter object.
Going back to the nesting ability. Say you have a table (bookmarked, say as "Contracts") with 16 cells (8 rows, 2 columns). But
three cells are commonly changed, or for some reason you want to get at them easily. You bookmark those cells (say, "IBM", "Oracle", "Pizza").
Code:
Dim oTable As Table
Dim oBM As Bookmark
Dim msg As String
Set oTable = ActiveDocument.Bookmarks("Contracts") _
.Range.Tables(1)
For Each oBM In oTable.Range.Bookmarks
[COLOR=red]' the table itself is a bookmark and
' is included in the collection
' so ignore it[/color red]
If oBM.Name <> "Contracts" Then
msg = msg & "The text of " & oBM.Name & _
" is " & oBM.Range.Text & vbCrLf
End If
Next
Set oTable = Nothing
MsgBox msg
would display:
The text of IBM is
text of THAT cell
The text of Oracle is
text of THAT cell
The text of Pizza is
text of THAT cell
If the purpose is to programmatically place/extract text at a location - use bookmarks.
If the purpose is to allow user input at a location - use formfields.
You can of course combine them. Say Section 1 has formfields, Section 2 is unprotected for user editing, Section 3 has formfields. But you want to get the formfield contents of just Section 3. Bookmark Section 3 (as "mySection3").
Code:
Dim r As Range
Dim oFF As Formfield
Dim msg As String
Set r = ActiveDocument.Bookmarks("mySection3").Range
For Each oFF In r.FormFields
msg = msg & oFF.Result & vbCrLf
Next
MsgBox msg
Set r = Nothing
would pick of the contents of just the formfields in Section 3.
Bookmarks - ummmm, real bookmarks - are a very powerful feature of Word. Again, if the purpose is to action programmatically at a location, use bookmarks. If the purpose is for user input, use formfields. IMO, if there is no user input required, there is no point in using formfields.
faq219-2884
Gerry
My paintings and sculpture