Re: Identify page on which a bookmark is located

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Bruce,
Glad to help. I learn as I read and participate in these forums.

Some useful keystroke shortcuts are:
ALT/F11 to toggle between document and VBA Editor
F1 for VBA contextual Help when the cursor is in a word in the VBA Editor
code.

No Help files installed? Try Google:
http://www.google.com/search?q=%22word%202003%22+install+VBA+help+file


Wow! Thanks for all of the information. I think I understand now that I
may have to proceed differently if the bookmark text rather than a point in
the document. I know what an insertion point is in Word, but it seems I
over-thought it in a VBA context.

For some reason my Help file contains none of the information about methods
and properties you have quoted, at least not by searching for the specific
information (that is, "Collapse" produces nothing in VBA Help). Maybe I
need to install SP3. For some reason that was not included with my
automatic updates. Or maybe the information appears under another heading.
My general experience with Help is that the information is often there, but
it is so poorly indexed it may as well not be.

Thanks too for clearing up Sections and Ranges, and for pointing out the way
to build a print string consisting of non-contiguous pages, just as that can
be done with the Print dialog. I hope I don't need to do that for this
project, but it is good to know I can.

I substituted your code:
ActiveDocument.Bookmarks("End").Range.Characters.First. _
Previous.Information(wdActiveEndAdjustedPageNumber)
ActiveDocument.Bookmarks("Start").Range _
.Information (wdActiveEndAdjustedPageNumber)

for my GoTo Bookmark code. Since the bookmarks were insertion points, as I
understand it there was no need to collapse anything, so I think my system
was OK, but this is more compact, which is my choice when all else is equal.
Your explanation of how the page number is determined is very helpful, as is
your explanation for the Type Mismatch error. I have saved this thread to
my personal Help files.

Thanks again for all of your help and explanation. As I mentioned, I don't
know why I don't have the information in VBA help, but the fact is I cannot
find it, so your quoted information has been quite valuable.

"Russ" <drsN0SPAMmikle@xxxxxxxxxxxxxxxxxxxxx> wrote in message
news:C34C3B4B.1E910%drsN0SPAMmikle@xxxxxxxxxxxxxxxxxxxxxxxx
Bruce says:
I don't understand what you mean by "insertion point" in this context.

The insertion point is the thin-blinking cursor position mark where you
are
typing text. Selection can be a selected word of text, a selected
paragraph
of text, etc.; or it can be no text selected but only the current cursor
position or insertion point. I avoid using the term Ohighlighted¹ for
selected text, because Word provides highlight colors to truly highlight
text, like a highlighter marker on paper. Selected text is text with
temporarily reversed colors for font and background to make it obvious to
the user what is selected and can be manipulated.

Also, in my research I came cross references to ³collapsing². Because of
my
lack of understanding I do not have a view one way or the other about
whether I
³want to collapse it to its start².

Here is what VBA Help says about the Collapse method:
=======Quote
Collapses a range or selection to the starting or ending position. After a
range or selection is collapsed, the starting and ending points are equal.

Syntax

expression.Collapse(Direction)

expression Required. An expression that returns a Range or Selection
object.

Direction Optional Variant. The direction in which to collapse the range
or
selection. Can be either of the following WdCollapseDirection constants:
wdCollapseEnd or wdCollapseStart. The default value is wdCollapseStart.

Remarks

If you use wdCollapseEnd to collapse a range that refers to an entire
paragraph, the range is located after the ending paragraph mark (the
beginning of the next paragraph). However, you can move the range back one
character by using the MoveEnd method after the range is collapsed, as
shown
in the following example.

Set myRange = ActiveDocument.Paragraphs(1).Range
myRange.Collapse Direction:=wdCollapseEnd
myRange.MoveEnd Unit:=wdCharacter, Count:=-1

======UnQuote

Collapsing may only matter if your bookmarks are not just insertion
points.
If they include text, then it depends on whether you want to include the
Start and End bookmarks ³full text² in the range of pages to print?
Collapsing the current selection changes the current selection to an
insertion point, either at the beginning or end or the previously selected
text.
So in order not to include both bookmarks text, you would collapse the
Start-bookmark to its end (then find the adjusted page number) and the
End-bookmark collapsed to its start (then find the adjusted page number).

Another thing is that I could not figure out how to use the Start
property. In
my attempts to use it I got a type mismatch compile error. VBA Help
documentation is spotty at best, so I can't figure out how to resolve that
(or
for that matter just how to use Start in the first place).

Here¹s one thing it says about the .Start property:
=======Quote
Returns or sets the starting character position of a selection, range, or
bookmark. Read/write Long.
=======UnQuote
Notice it says you can read or write to it, but then it says Long, which
means it is of a type number. The .Start and .End properties return a
number
indicating how many characters from the document beginning, which is at
.Start = 0 and .End = 0 or ActiveDocument.Range(0,0).

Here¹s one thing it says about the .Information property:
=======Quote
Returns information about the specified selection or range. Read-only
Variant.
=======UnQuote
Notice it is read only and returns information about a type selection or a
type range input. (not a type number input, as what is returned by the
.Start property; hence your type mismatch error.)


What this boils down to is, by collapsing a range or selection to the
start
or end it still remains a selection type or range type and can be used as
input to the .Information property. However you may not need to collapse
to
the end because, by default, the
Selection.Information(wdActiveEndAdjustedPageNumber) returns the page
number
on which the *ActiveEnd* of the selection ends.

Why use adjusted page argument - wdActiveEndAdjustedPageNumber?
Because, for instance, if the document is divided into different Word
sections with section breaks, each section can do its numbering
differently,
i.e. starting the page numbers counting from the number one again. And if
your bookmarks span across different sections and you gathered the
adjusted
page number and the section information with wdActiveEndSectionNumber, you
could ,for example, build up and use the string ³p2s2-p3s5² within the
.PrintOut method as shown below in the quoted Word help to print a range
of
pages from Page 2(Section 2) to Page 3(Section 5).

From regular Word Help:
=========Quote
Print specific pages and sections

You can print specific pages, one or more sections, or a range of pages in
more than one section. On the File menu, click Print.

To print In the Pages box
Noncontiguous pages Type the page numbers with commas between
them. Type the range of pages with a hyphen between the starting and
ending
numbers in the range. For example, to print pages 2, 4, 5, 6, and 8, type
2,4-6,8
A range of pages within a section Type p page number s section
number. For example, to print pages 5 through 7 in section 3, type
p5s3-p7s3
An entire section Type s section number. For example, type s3
Noncontiguous sections Type the section numbers with commas
between them. For example, type s3,s5
A range of pages across sections Type a range of page numbers
and
the sections that contain them with a hyphen between the starting and
ending
numbers in the range. For example, type p2s2-p3s5
=========UnQuote

To see if you needed to build up a more ³complex² print page string, you
would use ³if statements² to test if the bookmarks were in different
sections.

Choice between using Range or Selection?
Nowadays, the preferred method is to use Ranges for speed since Selection
requires Word to graphically indicate where the current selection is
located
and move it, if it changes.

Logically, the Range speed should have worked that way from the beginning.
It appeared that Word 97 had a bug in it that made Ranges slower than
Selection, but it was changed in the next version of Word to make Ranges
as
speedy as they should have been.
Selection still seems to work faster in Tables than Ranges at this time.
Someone suggested it was because of the way Table structures are arranged
in
memory.

Almost everything that can be defined by Selection can be defined by
Range.
When you record a macro, the code usually shows Selection because manually
you must select objects to indicate what you want to apply actions upon.
But
most of the time you can trim the resultant, recorded code of the
unnecessary options and change the Selections to Ranges for speed.

In your code, in order to use Ranges and not have to use the Goto
Bookmark,
which Selects the Bookmark text, maybe requiring you to Collapse the
Selection; you could use Ranges like this to find out which page the
Previous Character to the First Character of the bookmark named 'End'
Range
is located or the Next Character after the Last Character of the bookmark
named 'Start' Range is located:
ActiveDocument.Bookmarks("End").Range.Characters.First.Previous.Information
(wdActiveEndAdjustedPageNumber)
ActiveDocument.Bookmarks("Start").Range.Characters.Last.Next.Information
(wdActiveEndAdjustedPageNumber)
or
ActiveDocument.Bookmarks("Start").Range.Information
(wdActiveEndAdjustedPageNumber)
Since, by default, .Information (wdActiveEndAdjustedPageNumber) gives you
where the end of the range or selection is located.

Thanks again for hanging in there on this issue. After posting (but
before
receiving your reply) I tried wdActiveEndAdjustedPageNumber, but it did
not
change the outcome on that one document that was giving me trouble.
However, as I become more familiar with the options I found something
else
that seems to work:

Dim p1 As Long ' Start page
Dim p2 As Long ' End page

Selection.GoTo what:=wdGoToBookmark, Name:="DocEnd"
p2 = Selection.Information(wdActiveEndAdjustedPageNumber)
Selection.GoTo what:=wdGoToBookmark, Name:="DocStart"
p1 = Selection.Information(wdActiveEndAdjustedPageNumber)

ActiveDocument.PrintOut _
Range:=wdPrintFromTo, From:=CStr(p1), To:=CStr(p2)

Set rTmp = Nothing

I don't understand what you mean by "insertion point" in this context.
Also, in my research I came across references to "collapsing". Because
of
my lack of understanding I do not have a view one way or the other about
whether I "want to collapse it to its start". Another thing is that I
could
not figure out how to use the Start property. In my attempts to use it
I
got a type mismatch compile error. VBA Help documentation is spotty at
best, so I can't figure out how to resolve that (or for that matter just
how
to use Start in the first place).

Any further insights (or links to explanations) would be appreciated,
but in
particular does it seem that the code above will address the problem?
Again, I may want to print just page 1, or page 1 and 2, or page 7, or
other
combinations.
"Russ" <drsN0SPAMmikle@xxxxxxxxxxxxxxxxxxxxx> wrote in message
news:C34656F3.1E775%drsN0SPAMmikle@xxxxxxxxxxxxxxxxxxxxxxxx
Bruce,
Some quick observations.
I would use
wdActiveEndAdjustedPageNumber
For getting the end of the ranges. That automatically adjust page
numbers
to
any page number manipulation going on in the document.
------------------------------------
I'm not seeing why you are involving characters?

Basically the pseudocode is:
Set a new docstart2 range = to docstart.start, if docstart is not an
insertion point and you don't want to collapse it to its start.
Set a new docend2 range = to docend.end, if docsend is not an insertion
point and you don't want to collapse it to its end.

Find wdActiveEndAdjustedPageNumber of those insertion points.
(Optional, find wdActiveEndSectionNumber of those insertion points.)

Use that information in your printout command line.




It seems I spoke too soon. In some situations the last page is not
identified correctly. I tried adding your code (ShowAll), but it had
no
effect.
I tried inserting another bookmark and finding the page as I did with
the
starting bookmark, but no good. It is as if the second page doesn't
exist.
To test, I deleted everything except for the 2-page section I intended
to
print. The character count that I got by using the Word Count toolbar
was
the same as the one I got for AllChar using the code, but p2 in the
code
was
still 1, even though the last character was clearly on the second
page.
The strange part is that it usually works properly, but then on a very
similar document it doesn't work. When it doesn't work, there is
nothing
to
suggest why the two similar documents behave differently.
I have found that if I add characters to the second page I can
eventually
get Word to understand that the end of the section is on the second
page.
Maybe I will need to add a few hundred spaces or something when I run
into a
problem, but I like to think there is something more elegant than
that.

"BruceM" <bamoob@xxxxxxxxxxxxxxxx> wrote in message
news:ubcOiKkFIHA.4752@xxxxxxxxxxxxxxxxxxxxxxx
Thanks for the reply. As it happens the ShowAll did not accomplish
what
was needed (it still gave an incorrect number for the character
position
of the second bookmark. However, as I investigated further I think I
came
up with something. So far it seems to work in all situations.

Dim p1 As Long ' start page
Dim p2 As Long ' end page
Dim AllChar As Long ' Section character count

Dim rTmp As Range
Dim intSect As Integer

' Go to the first bookmark
Selection.GoTo What:=wdGoToBookmark, Name:="DocStart"

' Find the number of the section containing the bookmark
intSect = Selection.Information(wdActiveEndSectionNumber)
' Count the characters in the section
AllChar =

ActiveDocument.Sections(intSect).Range.ComputeStatistics(wdStatisticCharac>>>

t
er
sWithSpaces)
Set rTmp = ActiveDocument.Sections(intSect).Range
' At the first character in the section, find the page number
p1 = rTmp.Characters(1).Information(wdActiveEndPageNumber)
' At the last character in the section, find the page number
p2 = rTmp.Characters(AllChar).Information(wdActiveEndPageNumber)

ActiveDocument.PrintOut _
Range:=wdPrintFromTo, From:=CStr(p1), To:=CStr(p2)

Set rTmp = Nothing

This assumes the printout is all of one section. I expect the code
could
be adapted for printing multiple (including non-contiguous) sections.
I
think I can avoid those situations, but if not, I think there is a
way
to
work with it.

"Russ" <drsN0SPAMmikle@xxxxxxxxxxxxxxxxxxxxx> wrote in message
news:C34456C7.1E624%drsN0SPAMmikle@xxxxxxxxxxxxxxxxxxxxxxxx
Bruce,
Three things may trip you up:
1.Word usually determines page count from the current default
printer
driver.
2.Each section between section breaks may have different Page Setup
formatting. So you may also have to include the section numbers that
your
starting bookmark and ending bookmark are in.
3.Shown Hidden text (Index fields, etc.) may alter what
.Information...
may
see versus what Print Preview sees, if the option to not print
hidden
text
is on. If that is the case, then use the not show hidden text toggle
before
using .Information...

Dim blnShowAll As Boolean
blnShowAll = ActiveWindow.ActivePane.View.ShowAll
ActiveWindow.ActivePane.View.ShowAll = False
...most of your code
ActiveWindow.ActivePane.View.ShowAll = blnShowAll

I have code (obtained from this group in response to an earlier
question) to
print only the part of a document between two bookmarks. The
following
works inconsistently. Details are after the code. The code itself
is
in an
Add-In.

Dim x1 As Long ' start character of bookmark
Dim x2 As Long ' end character of bookmark
Dim p1 As Long ' start page
Dim p2 As Long ' end page

Dim rTmp As Range
Set rTmp = ActiveDocument.Range
' Allow for a bookmark at the beginning of document
If rTmp.Bookmarks("DocStart").Range.Start = 0 Then
x1 = 1
Else
x1 = rTmp.Bookmarks("DocStart").Range.Start
End If
x2 = rTmp.Bookmarks("DocEnd").Range.End
p1 = rTmp.Characters(x1).Information(wdActiveEndPageNumber)
p2 = rTmp.Characters(x2).Information(wdActiveEndPageNumber)

ActiveDocument.PrintOut _
Range:=wdPrintFromTo, From:=CStr(p1), To:=CStr(p2)

Set rTmp = Nothing

When the bookmarks DocStart and DocEnd are on the same page (so
that
only
one page is printed, which is the case most of the time) it seems
to
work as
intended. However, in other situations the results are mixed at
best.
For
instance, DocStart is on page 7, but p1 is 9 when I step through
the
code.
In the same document, if DocEnd is on page 8, it is identified as
11.
That
is, the variables p1 and p2 are 9 and 11 rather than 7 and 8.
Another problem I have noted is that I cannot find a place for the
DocEnd
bookmark in a two-page document (I want to print both pages) that
is
not
identifed as either page 1 or page 3. However, if I use the Word
Count
toolbar to count the number of characters, and replace x2 with that
number
(e.g. 2408), this line properly identifies p2 as 2:
p2 = rTmp.Characters(x2).Information(wdActiveEndPageNumber)

If I do not manually set x2 to 2408, it is identified as something
like
4500
(which is more than the total number of characters in the
document),
and
that line of code throws the following error:
5941 - The expected member of the collection does not exist

That is all the information I have been able to obtain. The
problem
seems
to be the same whenever it occurs: the character position of the
bookmarks
(the variables x1 and x2) are not identified properly.

If I could identify the page on which each of the bookmarks is
located,
I
could get the code to do what is needed. If this is not possible,
I
could
settle for setting the variables p1 and p2 manually for documents
in
which
problems occur, and have the code above start by testing whether
the
variables already have a value, and using that value instead of the
values
generated by the code, or something like that. I would rather not
do
that,
but I can accept a workaround if necessary.

I am using Word 2003. If it matters, the code above is designed to
include
the header and footer in the printout. Other code with which I
experimented
did not print the header and footer. It is better by far if I can
include
the header and footer.



--
Russ

drsmN0SPAMikleAThotmailD0Tcom.INVALID






--
Russ

drsmN0SPAMikleAThotmailD0Tcom.INVALID




--
Russ

drsmN0SPAMikleAThotmailD0Tcom.INVALID




--
Russ

drsmN0SPAMikleAThotmailD0Tcom.INVALID

.



Relevant Pages

  • Re: Identify page on which a bookmark is located
    ... previous character or next character and there are none at the beginning and ... "Collapse" produces nothing in VBA Help). ... for my GoTo Bookmark code. ... Collapses a range or selection to the starting or ending position. ...
    (microsoft.public.word.vba.general)
  • Re: Identify page on which a bookmark is located
    ... "Collapse" produces nothing in VBA Help). ... for my GoTo Bookmark code. ... Collapses a range or selection to the starting or ending position. ... character by using the MoveEnd method after the range is collapsed, ...
    (microsoft.public.word.vba.general)
  • Re: Identify page on which a bookmark is located
    ... "Collapse" produces nothing in VBA Help). ... for my GoTo Bookmark code. ... Collapses a range or selection to the starting or ending position. ... Returns or sets the starting character position of a selection, range, ...
    (microsoft.public.word.vba.general)
  • Re: Identify page on which a bookmark is located
    ... Here is what VBA Help says about the Collapse method: ... Collapses a range or selection to the starting or ending position. ... character by using the MoveEnd method after the range is collapsed, ... In your code, in order to use Ranges and not have to use the Goto Bookmark, ...
    (microsoft.public.word.vba.general)
  • RE: (repost): Very tough question, about HTML manipulation
    ... get the TextRange from the selection object. ... Let us call this the "Cursor", which we will use to go character by character. ... Collapse the Cursor range, using the collapsemethod, to the start of the Reference range. ...
    (microsoft.public.scripting.jscript)