PDA

View Full Version : Advice: Line and Paragraph Numbers - Reading into VBA



Mike Fitzgerald
06-16-2004, 10:00 PM
Hello all -- from someone who's comortable (sort of) around Excel VBA but feeling a trifle unsettled by some of Word's (2000) differences :giggle

This is one that I'm sure is staring me in the face somewhere since setting the following is obvious enough. But reading it? ...

OK, is there a ready way to return an absolute Word line number or paragraph number (either will do) to a VBA variable --

1. for the current cursor location (or current selection), and

2. for a nominated bookmark (without going to it) ?

FWIW my end purpose is to limit code execution to within defined regions of a document.

Thanks in advance,

Mike

Scottie P
06-16-2004, 10:36 PM
Hi Mike! Welcome to VBAX! :006:


Perhaps I am reading you wrong but lets take a shot at the bookmark part.
Are you saying to address the bookmark in VBA? If so, it would be something like
ActiveDocument.Bookmarks("MikesBkMk").Range


so that we can prescribe an action involving the bookmark of choice?

Sorry if I am off the course here.

Scott

Steiner
06-16-2004, 11:02 PM
Hi Mike,

getting the line number should be easy enough (at least once you know where to look for it ;) ):


MsgBox ActiveDocument.Bookmarks("tm_Test").Range.Information(wdFirstCharacterLineNumber)
or (for the cursor location)

MsgBox Selection.Range.Information(wdFirstCharacterLineNumber)


Getting the paragraph number is a bit more difficult as there is no such function in Word :mad: :

Function GetParNum(r As Range) As Integer
Dim rParagraphs As Range
Dim CurPos As Integer

r.Select
CurPos = ActiveDocument.Bookmarks("\startOfSel").Start
Set rParagraphs = ActiveDocument.Range(Start:=0, End:=CurPos)
GetParNum = rParagraphs.Paragraphs.Count
End Function


Call this one the following way for the cursor position:
MsgBox GetParNum(Selection.Range)

And for the bookmark:

MsgBox GetParNum(ActiveDocument.Bookmarks("tm_Test").Range)


Greets
Daniel

Mike Fitzgerald
06-16-2004, 11:40 PM
Hi Mike! Welcome to VBAX! :006:


Perhaps I am reading you wrong but lets take a shot at the bookmark part.
Are you saying to address the bookmark in VBA? If so, it would be something like
ActiveDocument.Bookmarks("MikesBkMk").Range


so that we can prescribe an action involving the bookmark of choice?

Sorry if I am off the course here.

Scott
Thanks Scott, however I don't want to operate on the bookmarks themselves, but constrain different text cleanup regimens to growing amounts of text that are either located between 2 bookmarks, or else follow the second one. And since they can float, I need to identify where the bookmarks are positioned at the current revision state of the document, and then test that the text to be subjected to a Replace operation (for example) is located somewhere in between them.

Anyway, it would seem that Steiner's illustration of the "Information" property is going to be the key to it.

Thanks again,

Mike

Mike Fitzgerald
06-17-2004, 02:25 AM
Hi Daniel,

Thanks for this -- the Information property looks like doing what I want. As you mention, knowing where to look is the gimmick. I'd actually tried "linenumber" in Help, and of course no prizes for guessing that it's unsearchable... :dunno


Hi Mike,

getting the line number should be easy enough (at least once you know where to look for it ;) ):

...snip...

Getting the paragraph number is a bit more difficult as there is no such function in Word :mad: :

...snip...

Greets
Daniel
Again, no real surprises at the end of the day. Just another of those "any app. designer with half a brain couldn't possibly have left THAT out, so it must be ME" things :help

Speaking of which, I've so far discovered that "Information(wdFirstCharacterLineNumber)" returns the line number relative to the current page, so I'll have to extract the page number as well. Simple enough now that you've pointed me to the relevant property list which contains other useful resources.

But since it's possible to put an absolute (from the start of the document) line number into the GoTo [count] argument, logic suggests that there should also exist, under some rock or another, a property that will likewise return the absolute number. But then using "logic" and "Microsoft" in the same breath does tend to expose one to ridicule...

As noted, I can look at both the page and line numbers but, just out of curiosity, does a property exist that holds the absolute number?

Thanks again,

Mike

Steiner
06-17-2004, 05:01 AM
Absolute line number :bug: ... yepp thanks MS, I guess will have to write my own function again :type :


Function GetAbsoluteLineNum(r As Range) As Integer
Dim i1 As Integer, i2 As Integer, Count As Integer

r.Select
Do
i1 = Selection.Information(wdFirstCharacterLineNumber)
Selection.GoTo what:=wdGoToLine, which:=wdGoToPrevious, Count:=1, Name:=""
Count = Count + 1
i2 = Selection.Information(wdFirstCharacterLineNumber)
Loop Until i1 = i2

r.Select
GetAbsoluteLineNum = Count
End Function



Now this one is really crude, but at least it seems to work. Just call it the same way as you did with the last ones.

@Dreamboat & Co:
Should you ever read this, could these small functions be worth adding to the KB?

Anne Troy
06-17-2004, 07:49 AM
ALL things that one might use should be added to the KB. I try to use what I feel might be searched keywords in either the Title of the entry or in the description. The answer is "definitely!"

:)

Scottie P
06-17-2004, 09:59 AM
Mike, my apologies for misreading you at first - as soon as Daniel posted I realized that you were working outside of the bookmarks (using them only as reference points to define actions between...and not inclusive).

I find that the Help file for Word 2000 is not as helpful as it could be - and the MVP site really had nothing comprehensive available (though I am sure that it is probably in there somewhere...if one could only find it:eek: )

Steiner, nice function! And thanks for putting that info together in your previous post; I am sure it will be helpful.

Scott

TonyJollans
06-17-2004, 12:11 PM
But then using "logic" and "Microsoft" in the same breath does tend to expose one to ridicule...



ROFL - so true!!

AFAIK there is no direct way to obtain an absolute line number. Gerry (fumei) will probably come up with something I don't know - he usually does - but, till then, this will give you the number of lines between the start of the document and the selection:


ActiveDocument.Range(0, Selection.Start).ComputeStatistics(wdStatisticLines)


The one problem with this is that if the Selection is at the start of a line, the number will not include that line, so a correction is needed for that, giving ..

ActiveDocument.Range(0, Selection.Start).ComputeStatistics(wdStatisticLines) _
- (ActiveDocument.Bookmarks("\Line").Start = Selection.Start)

fumei
06-18-2004, 06:06 PM
Thanks Tony, but I don't think I can do any better.

I am not not sure I followed all of this. If the idea was to determine, or identify, if text is between bookmarks, as part of a clean up routine, could you not just use the .End of the first bookmark, and the .Start of the second?

The current location can in fact be determined:

Dim CurPos as Long
CurPos = Selection.Range.Start

This can also apply to the location of the bookmarks. Therefore you can test, by number, the range between them.

Here is some long winded code (as I am sure Tony will find) :hi: , that determines if the current location is between two bookmarks.

Sub InRange()
Dim aDoc As Document
Dim pos1 As Long
Dim pos2 As Long
Dim CurPos As Long
Dim bolRightHere As Boolean

Set aDoc = ActiveDocument
pos1 = aDoc.Bookmarks("startme").End
pos2 = aDoc.Bookmarks("endme").Start
CurPos = Selection.Range.Start

bolRightHere = CurPos > pos1 And _
CurPos < pos2
If bolRightHere = True Then
MsgBox "Current location is: " & CurPos & vbCrLf & _
"This is within the defined input range." & vbCrLf & _
"Start= " & pos1 & ", End = " & pos2
Else
MsgBox "Current location is: " & CurPos & vbCrLf & _
"This is outside of the defined input range ." & vbCrLf & _
"Start= " & pos1 & ", End = " & pos2
End If
Set aDoc = Nothing
End Sub

fumei
06-18-2004, 06:10 PM
Oh, you may also want to collapse the selection first. While the code uses Selection.Start (which is not going to change - the start is the start), there may be issues in your clean up routines if the Selection.End is beyond the range you want to work with.

Not likely, but hey, it is that error trapping thing.

fumei
06-18-2004, 06:25 PM
Sorry, not together at all. My point was that you can determine ANY location by absolute number from the start of the document.

Dim r As Range
Set r = ActiveDocument.Range(Start:=672, End:=1236)
r.Select

will make the selection everything between the 672nd character, and the 1236th character. These were the absolute numbers for pos1 and pos2 in my test document. Of course, it is kind of dumb to use actual numbers since those locations can move. However, you certainly could determine the numbers at run time, and then use them. Say to grab a range except for the first three characters. Just increase the number of Start by 3.

Mike Fitzgerald
06-23-2004, 12:12 AM
Thanks to all who've thrown in ideas on this. You've given me plenty of very useful material to work with. Much appreciated! :hi:

Mike Fitzgerald

fumei
03-10-2005, 01:50 PM
Just reading back through this. Was it clear that the absolute number for ANY location, be it the Selection, a Range, a Bookmark - anything that uses a range, is very easy.

object.Range.Start gives the absolute number as Long. "Absolute" meaning the way Word counts, that is, by character. Duly noting that InlineShapes are counted as 1 character.

LeeFS
03-29-2010, 10:20 AM
Hi Mike,

getting the line number should be easy enough (at least once you know where to look for it ;) ):


MsgBox ActiveDocument.Bookmarks("tm_Test").Range.Information(wdFirstCharacterLineNumber)
or (for the cursor location)

MsgBox Selection.Range.Information(wdFirstCharacterLineNumber)


Getting the paragraph number is a bit more difficult as there is no such function in Word :mad: :

Function GetParNum(r As Range) As Integer
Dim rParagraphs As Range
Dim CurPos As Integer

r.Select
CurPos = ActiveDocument.Bookmarks("\startOfSel").Start
Set rParagraphs = ActiveDocument.Range(Start:=0, End:=CurPos)
GetParNum = rParagraphs.Paragraphs.Count
End Function


Call this one the following way for the cursor position:
MsgBox GetParNum(Selection.Range)

And for the bookmark:

MsgBox GetParNum(ActiveDocument.Bookmarks("tm_Test").Range)


Greets
Daniel
For Steiner: Greatly appreciate your GET PARAGRAPH NUMBER function - Many thanks: I've been looking for this solution for over a year! HOWEVER, I think it has one small but significant flaw: If the cursor is at the very start of a paragraph you get the previous paragraph number. You can see that by testing the same function at the start of the paragraph and one character to the right of the start.
This can be solved by adding "+1" at the end of the fifth line, i.e.:
CurPos = ActiveDocument.Bookmarks("\startOfSel").Start + 1
I hope you agree.
Lee

LeeFS
03-29-2010, 10:22 AM
Hi Mike,

getting the line number should be easy enough (at least once you know where to look for it ;) ):


MsgBox ActiveDocument.Bookmarks("tm_Test").Range.Information(wdFirstCharacterLineNumber)
or (for the cursor location)

MsgBox Selection.Range.Information(wdFirstCharacterLineNumber)


Getting the paragraph number is a bit more difficult as there is no such function in Word :mad: :

Function GetParNum(r As Range) As Integer
Dim rParagraphs As Range
Dim CurPos As Integer

r.Select
CurPos = ActiveDocument.Bookmarks("\startOfSel").Start
Set rParagraphs = ActiveDocument.Range(Start:=0, End:=CurPos)
GetParNum = rParagraphs.Paragraphs.Count
End Function


Call this one the following way for the cursor position:
MsgBox GetParNum(Selection.Range)

And for the bookmark:

MsgBox GetParNum(ActiveDocument.Bookmarks("tm_Test").Range)


Greets
Daniel
For Steiner: Greatly appreciate your GET PARAGRAPH NUMBER function - Many thanks: I've been looking for this solution for over a year! HOWEVER, I think it has one small but significant flaw: If the cursor is at the very start of a paragraph you get the previous paragraph number. You can see that by testing the same function at the start of the paragraph and one character to the right of the start.
This can be solved by adding "+1" at the end of the fifth line, i.e.:
CurPos = ActiveDocument.Bookmarks("\startOfSel").Start + 1
I hope you agree.
Lee