Solved

Navigating Bookmarks in Microsoft Word VBA

Posted on 2009-05-08
6
1,707 Views
Last Modified: 2012-05-06
Does anyone know of a robust method (macro) of navigating to the immediately next bookmark right after the current cursor position in a Document.

I am having a heck of a time.

For instance, let's say a large document has many bookmarks, and, let's say one bookmark is at character position #5000, the next bookmark is at character position #10000, and the cursor is at character position #7500.  When this macro is called, it should move the cursor from character position #7500 to position #10000.  (I don't know how to locate a Bookmark by the *line* number on which it is located.)

I *do* know that the Bookmark collection has "Start" and "End" properties.  These do *not* refer to *line* numbers, but, rather, to *character* positions.

So, in my first attempt at this, I thought it would be a simple matter of:

1)  Getting the absolute character position of the cursor via:
            Dim iCharNum As Long
            iCharNum = ActiveDocument.Range(1, Selection.Start).Characters.Count


2)  Indexing through all the "ActiveDocument.Bookmarks(i).Start" properties until I found the one that is:

      a)  closest to the cursor
                     and
      b)  either on or after the cursor

3)  Then, once I located the bookmark and its name call:

      Selection.GoTo What:=wdGoToBookmark, Name:=sName


This method works *great* . . . unless the document has *hyperlinks".  If it does, then the "Start" property of the bookmark is skewed.  (A hyperlink has a "Range.Start" and "Range.End" property.  Again, these are *character* positions, not line numbers.)

Back to the example:  let's look at the bookmark at character position #10000, therefore, its "Bookmark.Start" property is "10000".  Let's call this bookmark "B10000".
Let's put the cursor right at this bookmark.

Then call:
       "iCharNum = ActiveDocument.Range(1, Selection.Start).Characters.Count"
       to verify that BM10000 is, in fact, at 10000.

      At this point, iCharNum and BM10000.Start are equal.


Now let's paste a hyperlink over characters between the bookmark at character position #5000 and B10000.  But when we add it, let's be careful to paste over existing characters so that when the cursor is located right at BM10000, iCharNum is *still* 10000.

You will notice, however,  that the "Start" property of B10000 is *not* 10000 anymore even though the value of iCharNum *is* 10000.  That is, even though the physical position of B10000 did *not* change in the document, its "Start" property *did* change--it is skewed.  (I have found that the amount that it is skewed is a function of the number of hyperlinks and the values of each hyperlinks "Range.Start" and "Range.End" values; but I have found no consistency to this skewing and cannot develop a work-around).

Because of this, I can no longer depend on any bookmark's "Start" property anymore to determine where it is in the document.  Therefore, I cannot find the next bookmark to navigate to.

Please Help!

0
Comment
Question by:richelieu7777
  • 4
  • 2
6 Comments
 
LVL 23

Accepted Solution

by:
irudyk earned 500 total points
ID: 24336109
You could try using the current cursor location's vertical and horizontal position on the page using:
    Selection.Range.Information(wdVerticalPositionRelativeToPage)
    Selection.Range.Information(wdHorizontalPositionRelativeToPage)
Then you could get the vertical and horizontal position of each bookmark by using:
    ActiveDocument.Bookmarks(i).Range.Information(wdVerticalPositionRelativeToPage)
    ActiveDocument.Bookmarks(i).Range.Information(wdHorizontalPositionRelativeToPage)
Using the above methods you could then modify your code accordingly to select the desired bookmark.  The current cursor's location and each bookmarks horizontal postion would be used for times when the cursor location may be on the same vertical postion as the next bookmark.
0
 

Author Comment

by:richelieu7777
ID: 24336608
OK.  I'll try that in just a few minutes and let you know how it goes
0
 

Author Comment

by:richelieu7777
ID: 24338109
irudyk:
I don't that will work since there may be multiple bookmarks on multiple pages.   Therefore, it's possible that multiple bookmarks could have the same "wdVerticalPositionRelativeToPage" property.  For instance, if a document had 10 pages, and if each page had a bookmark on the top of each page, then each bookmark's "wdVerticalPositionRelativeToPage" property would be the same.  Therefore,  no way to distinguish one from another.

If there were a way of determining which *page* a bookmark was on and, correspondingly, which *page* the cursor was on, then that, combined with the "wdVerticalPositionRelativeToPage" should be enough information to uniquely identify a bookmark; but I can't find a way to identify a bookmark by the page on which it lies.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:richelieu7777
ID: 24338171
Aha.

I can use "ActiveDocument.Bookmarks(1).Range.Information(wdActiveEndPageNumber)"

to get the page number of both 1)  the cursor and 2) each bookmark
0
 

Author Closing Comment

by:richelieu7777
ID: 31579410
Additionally, you must also use:

 "ActiveDocument.Bookmarks(1).Range.Information(wdActiveEndPageNumber)"

to get the page number of both 1)  the cursor and 2) each bookmark.  Then, each bookmark can be uniquely identified by both its page number  and where it is on the page.
0
 
LVL 23

Expert Comment

by:irudyk
ID: 24338274
richelieu7777:
Yep, you are correct in that you must also use ActiveDocument.Bookmarks(1).Range.Information(wdActiveEndPageNumber) to get the page number of both the cursor and each bookmark so that each bookmark can be uniquely identified by both its page number and where it is on the page...poor testing on my part there!
I'm glad you were able to work through what I suggested into a solution that fully worked! Thanks for grade :)
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
Microsoft Office Picture Manager was included in Office 2003, 2007, and 2010, but not in Office 2013. Users had hopes that it would be in Office 2016/Office 365, but it is not. Fortunately, the same zero-cost technique that works to install it with …
Office 365 is currently available in five editions. Three of them are for business use: Office 365 Business Essentials, Office 365 Business, and Office 365 Business Premium. Two of them are for home/personal use: Office 365 Home and Office 365 Perso…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

895 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now