PDA

View Full Version : Cursor navigation within a range



paul1149
08-23-2011, 07:45 PM
Hi,
I sometimes have a need to convert flowing text to hard line breaks at the end of each line, because forum software sometimes runs lines too long.

So I came up with a macro that jumps the cursor to the end of each line, then adds a carriage return. My problem is containing the action within the selection (range), or alternately, stopping it at the end of the file.

This code is a mess, but at its heart you will see what I'm trying to do. I'm in Word 07.

Sub LineLengthFixed_NW()
' works only one line at a time
' don't know how to stop at selection or file end
Set rngtemp = Selection.Range
With rngtemp

Do
With Selection
.MoveRight unit:=wdCharacter, Count:=1
.EndKey unit:=wdLine
.TypeParagraph
End With
Loop

End With
End Sub

Jay Freedman
08-24-2011, 04:39 PM
The key to this is the InRange function. It returns True if one range is inside the other, or False if the first range isn't inside the second range. The other thing you need is to collapse the selection to its beginning position before the loop starts; otherwise the first pass through the loop will put the selection after the originally selected text.

Sub LineLengthFixed_NW()
Dim rngtemp As Range
Set rngtemp = Selection.Range
Selection.Collapse wdCollapseStart
Do
With Selection
.MoveRight unit:=wdCharacter, Count:=1
.EndKey unit:=wdLine
.TypeParagraph
End With
Loop Until Not Selection.Range.InRange(rngtemp)
End Sub

paul1149
08-24-2011, 05:16 PM
Thank you very much, Jay. That is awesome. Those were the two concepts I was struggling with.

Now to a little tweaking. I found that when I selected the whole file, I got an endless loop at the EOF. So I added a backstep to the range, to eliminate the final paragraph mark, and it seems to work:

Sub LineLengthFixed()
Dim rngtemp As Range
Set rngtemp = Selection.Range
rngtemp.MoveEnd unit:=wdCharacter, Count:=-1
Selection.Collapse wdCollapseStart
Do
With Selection
.MoveRight unit:=wdCharacter, Count:=1
.EndKey unit:=wdLine
.TypeParagraph
End With
Loop Until Not Selection.Range.InRange(rngtemp)
End Sub

However, I'm still getting multiple linefeed between paragraphs. Is there a clever way to ascertain whether the character at the line's end is a para mark? Then I could test for it, and skip the routine when there's a hit. Actually, that might take care of the EOF problem as well.

Thanks again,
Paul

Frosty
08-24-2011, 05:31 PM
Just a quick adjustment to Jay's code. The inRange is definitely useful (although there are a number of ways to limit do loops... could also look at comparing the .End property of both the selection and the original range).

However, you'll quickly see that running this code by using CTRL+A on the document will cause you a problem (as you will continue to add a paragraph to the end of the document, and since the rngTemp spans the whole document, you'll always be in the range).

There are a number of ways to address the endless loop possibilities of a Do...Loop... here's one, basically using Jay's code with two modifications.

(sorry to stick my nose in, Jay... I just happened to be loitering)

Sub LineLengthFixed_NW()
Dim rngtemp As Range
Set rngtemp = Selection.Range
'slightly adjust, but only if the last character is a paragraph mark
'(this takes care of if the entire document is selected, and
'also if you've selected an entire paragraph, and don't want the first line
'of the *next* paragraph to be adjusted too
If rngtemp.Characters.Last = vbCr Then
rngtemp.MoveEnd wdCharacter, -1
End If
Selection.Collapse wdCollapseStart
Do
With Selection
.MoveRight unit:=wdCharacter, Count:=1
.EndKey unit:=wdLine
'if there's already one here, don't bother adding another
If .Characters.Last <> vbCr Then
.TypeParagraph
End If
End With
Loop Until Not Selection.Range.InRange(rngtemp)
End Sub

Frosty
08-24-2011, 05:33 PM
oops, looks like I should have refreshed before posting... but yes, there are many ways to test it. I've got one way, although I think what you're describing may handle the loop a little more elegantly.

paul1149
08-24-2011, 05:58 PM
Frosty, that is perfect, and exactly what I had in mind, conceptually. It sails through the whole file without a snag. I think that first MoveEnd is still necessary, lest the loop continue indefinitely, even though it would be doing nothing.

Thanks much, Jay and Frosty.

Blessings,
Paul