Solved

Navigating Bookmarks in Microsoft Word VBA

Posted on 2009-05-08
6
1,733 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
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

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

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Entering a date in Microsoft Access can be tricky. A typo can cause month and day to be shuffled, entering the day only causes an error, as does entering, say, day 31 in June. This article shows how an inputmask supported by code can help the user a…
This article descibes how to create a connection between Excel and SAP and how to move data from Excel to SAP or the other way around.
In a previous video Micro Tutorial here at Experts Exchange (http://www.experts-exchange.com/videos/1358/How-to-get-a-free-trial-of-Office-365-with-the-Office-2016-desktop-applications.html), I explained how to get a free, one-month trial of Office …
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

821 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