Moving through document range including a table

G

Greg Maxey

Earlier today I scratched together a macro intended to allow a user to step through a document stopping at brightgreen highlighted text while skipping brightgreen highlighted text that had been previously flagged with a leading caret character. The user pointed out and I have confirmed that if the document contains a table and the the table has brightgreen highlighted text then the procedure won't move passed the first row containing the highlighted text.

Sub Test()
Dim oRng1 As Word.Range
Dim oRng2 As Word.Range
Set oRng1 = ActiveDocument.Range
Set oRng2 = Selection.Range
oRng1.start = oRng2.End 'It seems if in a table the oRng.Start is always at the beginning of the row that contains the selection
Continue:
With oRng1.Find
.MatchWildcards = True
.Highlight = True
.Execute
oRng1.Select
If oRng1.Characters.First = "^" Or _
oRng1.HighlightColorIndex <> wdBrightGreen Then
oRng1.Collapse wdCollapseEnd
If oRng1.End + 1 = ActiveDocument.End Then Exit Sub
GoTo Continue
Else
Selection.Collapse wdCollapseStart
End If
End With
End Sub
 
C

Cindy M -WordMVP-

Hi Greg,

Yes, this is "expected behavior" when using Word's FIND.
You can see the problem if you try to do any selecting in
Word's UI:
- text in cell: OK
- an entire cell: OK
- consecutive cells in the same row: OK
- one cell at the end of a row, plus the first cell in
the next row: doesn't work
- start in the top row, any cell but the first.
Shift+RightArrow to the end of the table, with the thought
of extending the selection to the end of the document. What
happens when you hit the end of the table? The entire table
is selected. That's what's "killing" your macro.

When using FIND, and tables are involved, you have to
- check whether the found range is in a table
- if yes, extend the search only to the end of the
current cell
- when the current cell has no more hits, move to the
next cell
- and repeat until the last cell in the table
- now move the range to just after the table and extend
to the end of the document to continue
Earlier today I scratched together a macro intended to
allow a user to step through a document stopping at
brightgreen highlighted text while skipping brightgreen
highlighted text that had been previously flagged with a
leading caret character. The user pointed out and I
have confirmed that if the document contains a table and
the the table has brightgreen highlighted text then the
procedure won't move passed the first row containing the
highlighted text. Sub Test()
Dim oRng1 As Word.Range
Dim oRng2 As Word.Range
Set oRng1 = ActiveDocument.Range
Set oRng2 = Selection.Range
oRng1.start = oRng2.End 'It seems if in a table the
oRng.Start is always at the beginning of the row that
contains the selection
Continue:
With oRng1.Find
..MatchWildcards = True
.Highlight = True
.Execute
oRng1.Select
If oRng1.Characters.First = "^" Or

oRng1.HighlightColorIndex <> wdBrightGreen Then
oRng1.Collapse wdCollapseEnd
If oRng1.End + 1 = ActiveDocument.End Then Exit Sub
GoTo Continue
Else
Selection.Collapse wdCollapseStart
End If
End With
End Sub

Cindy Meister
INTER-Solutions, Switzerland
http://homepage.swissonline.ch/cindymeister (last update
Jun 17 2005)
http://www.word.mvps.org

This reply is posted in the Newsgroup; please post any
follow question or reply in the newsgroup and not by e-mail
:)
 
G

Greg Maxey

Cindy,

Yes, I noticed the behaviour that you described and feared the solution
would involve some serious range manipulation. Still, I was hoping that the
reply would have included the necessary labor ;-). Thanks.
 
G

Greg Maxey

Cindy,

Still very crude, but this seems to be working. My am obviously not
thinking with a clear head as I don't seen a way to avoid the GoTo
statements. This macro is intended to find the next brightgreen
highlight after the IP and then stop to let the user edit. Perhaps
after I let it gel awhile I will see a better way. Do you or any
others have any ideas?

Sub StepThroughRange()
Dim oRng1 As Word.Range
Dim oRng2 As Word.Range
Dim oRowIndex As Long
Dim oColIndex As Long
Set oRng1 = ActiveDocument.Range
Set oRng2 = Selection.Range
oRng1.start = oRng2.End
If Not oRng2.Information(wdWithInTable) Then
Continue:
With oRng1.Find
.Highlight = True
.Execute
oRng1.Select
If oRng1.Characters.First = "^" Or _
oRng1.HighlightColorIndex <> wdBrightGreen Then
oRng1.Collapse wdCollapseEnd
If oRng1.End + 1 = ActiveDocument.Range.End Then
Selection.Collapse wdCollapseEnd
Exit Sub
End If
GoTo Continue
Else
Selection.Collapse wdCollapseStart
End If
End With
Else
Continue2:
oRowIndex = Selection.Information(wdStartOfRangeRowNumber)
oColIndex = Selection.Information(wdStartOfRangeColumnNumber)
Set oRng1 = Selection.Tables(1).Cell(oRowIndex, oColIndex).Range
Set oRng2 = Selection.Range
oRng1.MoveEnd wdCharacter, -1
oRng1.start = oRng2.End
With oRng1.Find
.Highlight = True
.Execute
oRng1.Select
If oRng1.Characters.First = "^" Or _
oRng1.HighlightColorIndex <> wdBrightGreen Then
oRng1.Collapse wdCollapseEnd
If oRng1.End + 1 = Selection.Tables(1).Cell(oRowIndex,
oColIndex).Range.End Then
Selection.Collapse wdCollapseEnd
Selection.Move wdCharacter, 1
End If
If Selection.Range.End + 1 <> Selection.Tables(1).Range.End Then
GoTo Continue2
Else
GoTo Continue
End If
Else
Selection.Collapse wdCollapseStart
End If
End With
End If
End Sub
 
C

Cindy M -WordMVP-

Hi Greg,
Still, I was hoping that the
reply would have included the necessary labor ;-).
Well, it's always good to let someone stretch their brain a
bit :) If I'd had an example at hand, I'd have copied it
in, but that Normal.dot was destroyed quite a while ago.
And you can't read German, so I couldn't point you to any
of the books it's published in, either :)

FWIW, I'm sure that I have posted it at least once in the
newsgroups on this server. If you prefer wading through
Google archives to working it out :)

Cindy Meister
INTER-Solutions, Switzerland
http://homepage.swissonline.ch/cindymeister (last update
Jun 17 2005)
http://www.word.mvps.org

This reply is posted in the Newsgroup; please post any
follow question or reply in the newsgroup and not by e-mail
:)
 
J

Jean-Guy Marcil

Greg Maxey was telling us:
Greg Maxey nous racontait que :
Cindy,

Still very crude, but this seems to be working. My am obviously not
thinking with a clear head as I don't seen a way to avoid the GoTo
statements. This macro is intended to find the next brightgreen
highlight after the IP and then stop to let the user edit. Perhaps
after I let it gel awhile I will see a better way. Do you or any
others have any ideas?
Here's something that almost works (you still have to figure out how to get
to, for example, the second "true" highlighted range in a cell that has a
"false" highlighted text preceding in the same cell.

'_______________________________________
Private boolSearchResult As Boolean
'_______________________________________
Sub StepThroughRange()

Dim oRng1 As Word.Range
Dim oRng2 As Word.Range

Set oRng1 = ActiveDocument.Range
Set oRng2 = Selection.Range

If oRng2.Information(wdWithInTable) Then
Set oRng1 = oRng2.Cells(1).Range
Else
oRng1.Start = oRng2.End
oRng1.End = oRng1.End - 1
End If

boolSearchResult = False

Do While Not boolSearchResult
SearchCaret oRng1
If oRng1.End = ActiveDocument.Range.End Then
MsgBox "Text was not found."
Exit Do
End If
Loop

End Sub
'_______________________________________

'_______________________________________
Function SearchCaret(ByRef rgeTarget As Range)

With rgeTarget.Find
.Highlight = True
.Execute
If rgeTarget.Characters.First = "^" Or _
rgeTarget.HighlightColorIndex <> wdBrightGreen Then
boolSearchResult = False
If rgeTarget.End + 1 = ActiveDocument.Range.End Then
rgeTarget.End = ActiveDocument.Range.End
Exit Function
Else
If rgeTarget.Information(wdWithInTable) Then
rgeTarget.End = rgeTarget.Cells(1).Range.End
rgeTarget.Collapse wdCollapseEnd
If rgeTarget.IsEndOfRowMark Then
If rgeTarget.End + 1 = rgeTarget.Tables(1).Range.End
Then
rgeTarget.SetRange rgeTarget.Start + 1,
ActiveDocument.Range.End - 1
Else
Set rgeTarget =
rgeTarget.Tables(1).Cell(rgeTarget.Rows(1).Index + 1, 1).Range
End If
Else
Set rgeTarget = rgeTarget.Cells(1).Range
End If
Else
rgeTarget.Collapse wdCollapseEnd
rgeTarget.End = ActiveDocument.Range.End - 1
End If
End If
Else
rgeTarget.Select
Selection.Collapse wdCollapseStart
boolSearchResult = True
MsgBox "Text was found."
End If
End With

End Function
'_______________________________________

--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
G

Greg Maxey

JGM,

Thanks. I'll look at your method. Since last post the fog has cleared
a bit and I have managed to eliminate the GoTo statements like this:

Sub StepThroughRange()
Dim oRng1 As Word.Range
Dim oRng2 As Word.Range
Dim oRowIndex As Long
Dim oColIndex As Long
Set oRng1 = ActiveDocument.Range
Set oRng2 = Selection.Range
oRng1.start = oRng2.End
If oRng2.Information(wdWithInTable) Then
Do
oRowIndex = Selection.Information(wdStartOfRangeRowNumber)
oColIndex = Selection.Information(wdStartOfRangeColumnNumber)
Set oRng1 = Selection.Tables(1).Cell(oRowIndex, oColIndex).Range
Set oRng2 = Selection.Range
oRng1.MoveEnd wdCharacter, -1
oRng1.start = oRng2.End
With oRng1.Find
.Highlight = True
.Execute
oRng1.Select
If oRng1.Characters.First = "^" Or _
oRng1.HighlightColorIndex <> wdBrightGreen Then
oRng1.Collapse wdCollapseEnd
If oRng1.End + 1 = Selection.Tables(1).Cell _
(oRowIndex, oColIndex).Range.End Then
Selection.Collapse wdCollapseEnd
Selection.Move wdCharacter, 1
End If
If Selection.Range.End + 1 = Selection.Tables(1).Range.End Then
Selection.Move wdCharacter, 1
Exit Do
End If
Else
Selection.Collapse wdCollapseStart
Exit Do
End If
End With
Loop
Else
With oRng1.Find
.Highlight = True
Do
.Execute
oRng1.Select
If oRng1.Characters.First = "^" Or _
oRng1.HighlightColorIndex <> wdBrightGreen Then
oRng1.Collapse wdCollapseEnd
If oRng1.End + 1 = ActiveDocument.Range.End Then
Selection.Collapse wdCollapseEnd
Exit Sub
End If
Else
Selection.Collapse wdCollapseStart
Exit Do
End If
Loop
End With
End If
End Sub
 
G

Greg Maxey

JGM,

Nice construction. Seems the method I scrabbled through catches the
repeated valid highlight following preceeding invalid highlight
preceeding in the same cell. I will call that luck and consider the
project finished. Thanks.
 
J

Jean-Guy Marcil

Greg Maxey was telling us:
Greg Maxey nous racontait que :
JGM,

Thanks. I'll look at your method. Since last post the fog has
cleared a bit and I have managed to eliminate the GoTo statements
like this:

Sub StepThroughRange()
Dim oRng1 As Word.Range
Dim oRng2 As Word.Range
Dim oRowIndex As Long
Dim oColIndex As Long
Set oRng1 = ActiveDocument.Range
Set oRng2 = Selection.Range
oRng1.start = oRng2.End
If oRng2.Information(wdWithInTable) Then
Do
oRowIndex = Selection.Information(wdStartOfRangeRowNumber)
oColIndex = Selection.Information(wdStartOfRangeColumnNumber)
Set oRng1 = Selection.Tables(1).Cell(oRowIndex, oColIndex).Range
Set oRng2 = Selection.Range
oRng1.MoveEnd wdCharacter, -1
oRng1.start = oRng2.End
With oRng1.Find
.Highlight = True
.Execute
oRng1.Select
If oRng1.Characters.First = "^" Or _
oRng1.HighlightColorIndex <> wdBrightGreen Then
oRng1.Collapse wdCollapseEnd
If oRng1.End + 1 = Selection.Tables(1).Cell _
(oRowIndex, oColIndex).Range.End Then
Selection.Collapse wdCollapseEnd
Selection.Move wdCharacter, 1
End If
If Selection.Range.End + 1 = Selection.Tables(1).Range.End Then
Selection.Move wdCharacter, 1
Exit Do
End If
Else
Selection.Collapse wdCollapseStart
Exit Do
End If
End With
Loop
Else
With oRng1.Find
.Highlight = True
Do
.Execute
oRng1.Select
If oRng1.Characters.First = "^" Or _
oRng1.HighlightColorIndex <> wdBrightGreen Then
oRng1.Collapse wdCollapseEnd
If oRng1.End + 1 = ActiveDocument.Range.End Then
Selection.Collapse wdCollapseEnd
Exit Sub
End If
Else
Selection.Collapse wdCollapseStart
Exit Do
End If
Loop
End With
End If
End Sub

Just curious, have you tested it with more than one table in a document?
I haven't tested your code, but after a quick look, it seems that if I
encounter a false green text in a table while in the second loop, the code
will fail as you originally noticed. This is why I placed the table checking
stuff in the search function and repeatedly called it until I got to the end
of the document or until I found a valid green text.

Or maybe it is my turn to be in the fog...

--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
G

Greg Maxey

JGM,

No I didn't test very well :-(. I realized I was getting runtime
errors at the end of the rows in some situations. I have now tested
with mulitiple tables with mixed highlighting and some empty rows. I
had to throw in an error handler and there could still be bugs, but
this seems to being working:

Sub StepThroughRange()
Dim oRng1 As Word.Range
Dim oRng2 As Word.Range
Dim oRowIndex As Long
Dim oColIndex As Long
Set oRng1 = ActiveDocument.Range
Set oRng2 = Selection.Range
oRng1.start = oRng2.End
Do
NextRow:
If oRng2.Information(wdWithInTable) Then
Set oRng2 = Selection.Range
oRowIndex = Selection.Information(wdStartOfRangeRowNumber)
oColIndex = Selection.Information(wdStartOfRangeColumnNumber)
On Error GoTo Handler
Set oRng1 = Selection.Tables(1).Cell(oRowIndex, oColIndex).Range
oRng1.MoveEnd wdCharacter, -1
oRng1.start = oRng2.End
With oRng1.Find
.Highlight = True
.Execute
oRng1.Select
If oRng1.Characters.First = "^" Or _
oRng1.HighlightColorIndex <> wdBrightGreen Then
oRng1.Collapse wdCollapseEnd
If oRng1.End + 1 = Selection.Tables(1).Cell _
(oRowIndex, oColIndex).Range.End Then
Selection.Collapse wdCollapseEnd
Selection.Move wdCharacter, 1
End If
If Selection.Range.End + 1 = Selection.Tables(1).Range.End Then
Selection.Move wdCharacter, 1
Set oRng2 = Selection.Range
Exit Do
End If
Else
Selection.Collapse wdCollapseStart
Exit Do
End If
End With
Else
Exit Do
End If
Loop
If Not oRng2.Information(wdWithInTable) Then
With oRng1.Find
.Highlight = True
Do
.Execute
oRng1.Select
If oRng1.Information(wdWithInTable) Then Exit Sub
If oRng1.Characters.First = "^" Or _
oRng1.HighlightColorIndex <> wdBrightGreen Then
oRng1.Collapse wdCollapseEnd
If oRng1.End + 1 = ActiveDocument.Range.End Then
Selection.Collapse wdCollapseEnd
Exit Sub
End If
Else
Selection.Collapse wdCollapseStart
Exit Do
End If
Loop
End With
End If
Exit Sub
Handler:
If Err.Number = 5941 Then
Selection.Move wdCharacter, 1
Resume NextRow
End If
End Sub
 
J

Jean-Guy Marcil

Greg Maxey was telling us:
Greg Maxey nous racontait que :
JGM,

No I didn't test very well :-(. I realized I was getting runtime
errors at the end of the rows in some situations. I have now tested
with mulitiple tables with mixed highlighting and some empty rows. I
had to throw in an error handler and there could still be bugs, but
this seems to being working:

Sub StepThroughRange()
Dim oRng1 As Word.Range
Dim oRng2 As Word.Range
Dim oRowIndex As Long
Dim oColIndex As Long
Set oRng1 = ActiveDocument.Range
Set oRng2 = Selection.Range
oRng1.start = oRng2.End
Do
NextRow:
If oRng2.Information(wdWithInTable) Then
Set oRng2 = Selection.Range
oRowIndex = Selection.Information(wdStartOfRangeRowNumber)
oColIndex = Selection.Information(wdStartOfRangeColumnNumber)
On Error GoTo Handler
Set oRng1 = Selection.Tables(1).Cell(oRowIndex, oColIndex).Range
oRng1.MoveEnd wdCharacter, -1
oRng1.start = oRng2.End
With oRng1.Find
.Highlight = True
.Execute
oRng1.Select
If oRng1.Characters.First = "^" Or _
oRng1.HighlightColorIndex <> wdBrightGreen Then
oRng1.Collapse wdCollapseEnd
If oRng1.End + 1 = Selection.Tables(1).Cell _
(oRowIndex, oColIndex).Range.End Then
Selection.Collapse wdCollapseEnd
Selection.Move wdCharacter, 1
End If
If Selection.Range.End + 1 = Selection.Tables(1).Range.End Then
Selection.Move wdCharacter, 1
Set oRng2 = Selection.Range
Exit Do
End If
Else
Selection.Collapse wdCollapseStart
Exit Do
End If
End With
Else
Exit Do
End If
Loop
If Not oRng2.Information(wdWithInTable) Then
With oRng1.Find
.Highlight = True
Do
.Execute
oRng1.Select
If oRng1.Information(wdWithInTable) Then Exit Sub
If oRng1.Characters.First = "^" Or _
oRng1.HighlightColorIndex <> wdBrightGreen Then
oRng1.Collapse wdCollapseEnd
If oRng1.End + 1 = ActiveDocument.Range.End Then
Selection.Collapse wdCollapseEnd
Exit Sub
End If
Else
Selection.Collapse wdCollapseStart
Exit Do
End If
Loop
End With
End If
Exit Sub
Handler:
If Err.Number = 5941 Then
Selection.Move wdCharacter, 1
Resume NextRow
End If
End Sub


Did I miss something, or does the line
If oRng1.Information(wdWithInTable) Then Exit Sub
mean that if a "false" green (or any other colour) is found in a table, you
quit the sub?
What if there is a true match further down in the document?
The user has to run the macro again just in case?
And what if there are many tables with false colours before you get to an
actual true match?

I still believe that you have to separate the actual "find" from the calling
it so that you can call it repeatedly, wherever you end up in the document.
The way you have it, you check if the initial selection is in a table and
you have all that nice code to handle that. But later, if you find a false
match within a table, you cannot get to that code unless you start using
GoTo and this will get complicated this could be a case of spaghetti code!.
If I had time I would fix my code so that it would create sub-ranges within
cells whenever a false match is found within a cell (by checking if the
found false match end of range matches the end of the cell range, if not,
create a sub range with what is left in the cell range instead of going to
the next cell).

Or have I missed something again, or is it that this was part of the
poster's requirement (I mean, stopping execution if a false match is found
within a table after launching the macro)?


--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
G

Greg Maxey

JGM,

No you didn't miss anything. Actually that was an astute observation.
I noticed that if the document ended in a table there was a continous
loop situation and I thought that fixed it. You can replace that line
with:

If Not .Found Then Exit Sub

As I only became interested in this due to a posters question, I
haven't taken the time myself to thoroughly test or debug. That said,
yes it borders on spagetti code ;-)

I notice your first proposal continues to find the first instance of
brightgreen in the cell with the IP.

Example:

Cell 1:

BG some text Y some text BG some text.

It finds the first BG. If the user edits and leave the cursor at the
start of some text and runs the code again it finds and stops at the
first BG again.

Like you, I had or have time I might try to modify you code to solve
that issue.

Cheers.
 
G

Greg Maxey

Jean-Guy Marcil said:
Greg Maxey was telling us:
Greg Maxey nous racontait que :



Did I miss something, or does the line
If oRng1.Information(wdWithInTable) Then Exit Sub
mean that if a "false" green (or any other colour) is found in a table, you
quit the sub?
What if there is a true match further down in the document?
The user has to run the macro again just in case?
And what if there are many tables with false colours before you get to an
actual true match?

I still believe that you have to separate the actual "find" from the calling
it so that you can call it repeatedly, wherever you end up in the document.
The way you have it, you check if the initial selection is in a table and
you have all that nice code to handle that. But later, if you find a false
match within a table, you cannot get to that code unless you start using
GoTo and this will get complicated this could be a case of spaghetti code!.
If I had time I would fix my code so that it would create sub-ranges within
cells whenever a false match is found within a cell (by checking if the
found false match end of range matches the end of the cell range, if not,
create a sub range with what is left in the cell range instead of going to
the next cell).

Or have I missed something again, or is it that this was part of the
poster's requirement (I mean, stopping execution if a false match is found
within a table after launching the macro)?


--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
J

Jean-Guy Marcil

Greg Maxey was telling us:
Greg Maxey nous racontait que :
JGM,

No you didn't miss anything. Actually that was an astute observation.
I noticed that if the document ended in a table there was a continous

I didn't test for that instance with my code... I guess I would have to
change something as well...
loop situation and I thought that fixed it. You can replace that line
with:

If Not .Found Then Exit Sub

As I only became interested in this due to a posters question, I
haven't taken the time myself to thoroughly test or debug. That said,
yes it borders on spagetti code ;-)

I notice your first proposal continues to find the first instance of
brightgreen in the cell with the IP.

Example:

Cell 1:

BG some text Y some text BG some text.

It finds the first BG. If the user edits and leave the cursor at the
start of some text and runs the code again it finds and stops at the
first BG again.

I know, this is what I meant when I wrote:

"Here's something that almost works (you still have to figure out how to get
to, for example, the second "true" highlighted range in a cell that has a
"false" highlighted text preceding in the same cell."

in my first post in this thread
Like you, I had or have time I might try to modify you code to solve
that issue.

And this is why I suggested the following in my previous post:

"If I had time I would fix my code so that it would create sub-ranges within
cells whenever a false match is found within a cell (by checking if the
found false match end of range matches the end of the cell range, if not,
create a sub range with what is left in the cell range instead of going to
the next cell)."

:)

--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
G

Greg Maxey

JGM,

It took some thought and trial and error, but I think I have your
version working now as it should. There is a little redundancy in
setting the ranges on the first pass, but they hae to be reset with
each iteration of the DO so I figure it is OK:

Option Explicit
Private boolSearchResult As Boolean
Sub StepThrough()
Dim oRng1 As Word.Range
Dim oRng2 As Word.Range
Set oRng1 = ActiveDocument.Range
Set oRng2 = Selection.Range
If oRng2.Information(wdWithInTable) Then
Set oRng1 = oRng2.Cells(1).Range
oRng1.End = oRng1.End - 1
Else
oRng1.Start = oRng2.End
oRng1.End = oRng1.End - 1
End If
boolSearchResult = False
Do While Not boolSearchResult
Set oRng2 = Selection.Range
oRng1.Start = oRng2.End
SearchCaret oRng1
If oRng1.End = ActiveDocument.Range.End Then
MsgBox "Text was not found."
Exit Do
End If
Loop
End Sub
Function SearchCaret(ByRef rgeTarget As Range)
With rgeTarget.Find
.Highlight = True
.Execute
rgeTarget.Select
If rgeTarget.Characters.First = "^" Or _
rgeTarget.HighlightColorIndex <> wdBrightGreen Then
boolSearchResult = False
rgeTarget.Collapse wdCollapseEnd
rgeTarget.Select
If Not .Found Then
If Selection.Information(wdWithInTable) Then
Selection.Move wdCharacter, 1
Else
boolSearchResult = True
End If
End If
Exit Function
If rgeTarget.End + 1 = ActiveDocument.Range.End Then
rgeTarget.End = ActiveDocument.Range.End
Exit Function
Else
If rgeTarget.Information(wdWithInTable) Then
rgeTarget.End = rgeTarget.Cells(1).Range.End
rgeTarget.Collapse wdCollapseEnd
If rgeTarget.IsEndOfRowMark Then
If rgeTarget.End + 1 = rgeTarget.Tables(1).Range.End Then
rgeTarget.SetRange rgeTarget.Start + 1,
ActiveDocument.Range.End - 1
Else
Set rgeTarget =
rgeTarget.Tables(1).Cell(rgeTarget.Rows(1).Index + 1, 1).Range
End If
Else
Set rgeTarget = rgeTarget.Cells(1).Range
End If
Else
rgeTarget.Collapse wdCollapseEnd
rgeTarget.End = ActiveDocument.Range.End - 1
End If
End If
Else
rgeTarget.Select
Selection.Collapse wdCollapseStart
boolSearchResult = True
End If
End With
End Function
 
G

Greg Maxey

JGM,

After a closer look, it appears that the Function can be simplfied to:

Function SearchCaret(ByRef rgeTarget As Range)
With rgeTarget.Find
.Highlight = True
.Execute
If rgeTarget.Characters.First = "^" Or _
rgeTarget.HighlightColorIndex <> wdBrightGreen Then
boolSearchResult = False
rgeTarget.Collapse wdCollapseEnd
rgeTarget.Select
If Not .Found Then
If Selection.Information(wdWithInTable) Then
Selection.Move wdCharacter, 1
Else
boolSearchResult = True
End If
End If
Exit Function
If rgeTarget.End + 1 = ActiveDocument.Range.End Then
rgeTarget.End = ActiveDocument.Range.End
Exit Function
End If
Else
rgeTarget.Select
Selection.Collapse wdCollapseStart
boolSearchResult = True
End If
End With
End Function
 
J

Jean-Guy Marcil

Greg Maxey was telling us:
Greg Maxey nous racontait que :
JGM,

It took some thought and trial and error, but I think I have your
version working now as it should. There is a little redundancy in
setting the ranges on the first pass, but they hae to be reset with
each iteration of the DO so I figure it is OK:

Sorry to pick on you like this, but this version still does not work as it
should, and, I believe that in your eagerness to simplify the code (which
desperately needed to be simplified) you created other problems.
One thing I had done was to keep all the range setting code in the
SearchCaret function (except for the intial bit, of course), this is why is
used the ByRef keyword.
Here, you reset the range within the Loop and you keep using the Selection
object, which I avoid as much as possible.
Within the loop you have:
Set oRng2 = Selection.Range
oRng1.Start = oRng2.End
In your code, oRng2 becomes the point at which the function stop searching,
then you equate the end point of this with the starting point of oRng1,
which is practically the same thing because oRng1 was set by rgeTarget in
the SearchCaret function (through the ByRef keyword).

Another problem is related to this bit of code:

If rgeTarget.Characters.First = "^" Or _
rgeTarget.HighlightColorIndex <> wdBrightGreen Then
boolSearchResult = False
rgeTarget.Collapse wdCollapseEnd
rgeTarget.Select
If Not .Found Then
If Selection.Information(wdWithInTable) Then
Selection.Move wdCharacter, 1
Else
boolSearchResult = True
End If
End If
Exit Function

Here, ".Found" is always true whenever you find highlighted stuff, so you
never get to the code inside this If statement that this conditional test
introduces. But, if it were False, it would mean that from the range
starting point to the end of the document no highlighted was found, in which
case it is not necessary to adjust any range since we are done.
Finally, all this is followed by an Exit Function line, which means that
whatever code inside the the "If rgeTarget.Characters.First = "^" Or _" that
follows this Exit line is never even executed.

OTOH, you were absolutely right that the function could be simplified. When
I first wrote my version, I ran into a problem in a table, so I solve that
problem, which created another one, and so on.
In the end I had a truck load of code that was not necessary, if only I had
rethought the whole thing from scratch as you did.

Here is yet another version...!

Option Explicit
Private boolSearchResult As Boolean
Sub StepThrough()
Dim oRng1 As Word.Range
Dim oRng2 As Word.Range
Set oRng1 = ActiveDocument.Range
Set oRng2 = Selection.Range
If oRng2.Information(wdWithInTable) Then
Set oRng1 = oRng2.Cells(1).Range
oRng1.End = oRng1.End - 1
Else
oRng1.Start = oRng2.End
oRng1.End = oRng1.End - 1
End If
boolSearchResult = False
Do While Not boolSearchResult
SearchCaret oRng1
If oRng1.End = ActiveDocument.Range.End Then
MsgBox "Text was not found."
Exit Do
End If
Loop
End Sub
Function SearchCaret(ByRef rgeTarget As Range)
With rgeTarget.Find
.Highlight = True
.Execute
If rgeTarget.Characters.First = "^" Or _
rgeTarget.HighlightColorIndex <> wdBrightGreen Then
boolSearchResult = False
rgeTarget.Collapse wdCollapseEnd
If rgeTarget.End + 1 = ActiveDocument.Range.End Then
rgeTarget.End = ActiveDocument.Range.End
Exit Function
Else
If rgeTarget.Information(wdWithInTable) Then
rgeTarget.MoveEnd wdCharacter, 1
rgeTarget.Collapse wdCollapseEnd
Else
rgeTarget.End = ActiveDocument.Range.End - 1
End If
End If
Else
rgeTarget.Select
Selection.Collapse wdCollapseStart
boolSearchResult = True
End If
End With
End Function

--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
G

Greg Maxey

JGM,



I don't consider it picking on me. I enjoy the dialog. I am analyzing your
comments regarding my last version and evaluating yours.



First let me make sure that you know how I envision this macro working. The
user has a smattering of highlighted text (in multi-colors) through a
document. The important color is brightgreen some of the important color
text he has already reviewed and flagged with a leading carat symbol. No
the user wants to start at the beginning of the document and step through
the range stopping to review and edit the unflagged bright green text. He
put the cursor at the start of the document and fires the macro. The IP
appears at the start of the first found unflagged brightgreen text and the
macro stops. The user edits the text and leaves the cursor to the right
(following the edited text). He fires the macro again.



The first thing I noticed is that your new version will not move from one
cell containing brightgreen text to the next cell or from the first instance
of highlighted text in a cell to subsequent instances. It repeatedly goes
back (loops) and stops at first found bit of text in the cell. If the IP is
at the end of a cell and the macro is fired instead of looking forward for
the next bit of text, your goes back to the previous highlighted text in the
cell.



Mine doesn't do that. If the cursor is to the right of the first bit of
highlighted text in a cell and I run the macro again it stops at the next
bit in that cell or at the next bit in a subsequent cell, etc.



If I put the cursor between two bits of unflagged brightgreen text in a cell
and step through the code then rgeTarget consists of the range of text
between the IP and the end of the cell. In your last version rgeTarget
consist of entire cell range. Hence it "finds" the text before the cursor.



To fix this I set the start range of oRng1 to the end range of oRng2 in the
DO statement:



Do While Not boolSearchResult

Set oRng2 = Selection.Range

oRng1.Start = oRng2.End

As for the If Not .Found Statement, without it if the IP is in a table cell
that contains no more hightlighted text and there is no more subsequent
highlighted text in the document a continuous loop occurs.



So with all that said, this is what I have left:



Private bEndProcessing as Boolean

Sub StepThrough()

Dim oRng1 As Word.Range

Dim oRng2 As Word.Range

Set oRng1 = ActiveDocument.Range

Set oRng2 = Selection.Range

If oRng2.Information(wdWithInTable) Then

Set oRng1 = oRng2.Cells(1).Range

oRng1.End = oRng1.End - 1

Else

oRng1.Start = oRng2.End

oRng1.End = oRng1.End - 1

End If

bEndProcessing = False

Do While Not bEndProcessing

Set oRng2 = Selection.Range

oRng1.Start = oRng2.End

SearchCaret oRng1

If oRng1.End + 1 = ActiveDocument.Range.End Then

MsgBox "End of Document. Text not found."

Exit Do

End If

Loop

End Sub

Function SearchCaret(ByRef rgeTarget As Range)

With rgeTarget.Find

.Highlight = True

.Execute

If rgeTarget.Characters.First = "^" Or _

rgeTarget.HighlightColorIndex <> wdBrightGreen Then

bEndProcessing = False

rgeTarget.Collapse wdCollapseEnd

rgeTarget.Select

If Not .Found Then

If Selection.Information(wdWithInTable) Then

Selection.Move wdCharacter, 1

Else

bEndProcessing = True

End If

End If

Exit Function

Else

rgeTarget.Select

Selection.Collapse wdCollapseStart

bEndProcessing = True

End If

End With

End Function



There remains at least one issue that I haven't bothered to try to resolve.
If the IP is in a table with no more text to find and there is no more text
to find in subsequent text, the cursor rests at the end of the Table and the
msgbox doesn't pop. The users will have to fire the macro again. Seems
silly to kill brain cells over ;-)
 
J

Jean-Guy Marcil

Greg Maxey was telling us:
Greg Maxey nous racontait que :
JGM,



I don't consider it picking on me. I enjoy the dialog. I am
analyzing your comments regarding my last version and evaluating
yours.


First let me make sure that you know how I envision this macro
working. The user has a smattering of highlighted text (in
multi-colors) through a document. The important color is brightgreen
some of the important color text he has already reviewed and flagged
with a leading carat symbol. No the user wants to start at the
beginning of the document and step through the range stopping to
review and edit the unflagged bright green text. He put the cursor
at the start of the document and fires the macro. The IP appears at
the start of the first found unflagged brightgreen text and the macro
stops. The user edits the text and leaves the cursor to the right
(following the edited text). He fires the macro again.

Yep, I got that part, although I did not really test the code by doing a
systematic approach as you described, but this time I did.
The first thing I noticed is that your new version will not move from
one cell containing brightgreen text to the next cell or from the
first instance of highlighted text in a cell to subsequent instances.
It repeatedly goes back (loops) and stops at first found bit of text
in the cell. If the IP is at the end of a cell and the macro is
fired instead of looking forward for the next bit of text, your goes
back to the previous highlighted text in the cell.

I did not observe that behaviour. I just tried again with a 3x3 table with 5
bits of "un-careted" bright green text, with an instance of 2 of them in the
same cell separated by a few paragraphs.
I fired my macro and it found all of them in succession (after each
successful found I added a caret at the beginning of the bright green text
and then placed the IP right after the said bright green text. Maybe this is
where I get confused. I assumed that the caret was to indicate that the
bright green text had already been reviewed, so I assumed, probably wrongly,
that whenever a bit of unflagged green text is found, the user edits it and
then flags it (byadding a caret) so the macro would not found it again. If
this is not the case, then, with my version, the user has to place the IP in
the next cell before firing the macro again.).

This second version performs as well as the first, except that the first
could not handle two bits of green text in the same cell. Now, with your
input, this second version does find those instances.
Mine doesn't do that. If the cursor is to the right of the first bit
of highlighted text in a cell and I run the macro again it stops at
the next bit in that cell or at the next bit in a subsequent cell,
etc.

The only time I noticed that with my version is when you bypass a bit of
"un-careted" bright green text in a cell. So, if you place the IP after some
unflagged bright green text, the macro will find it, but if the preceding
bit of bright green text in the same cell is already flagged, the macro
ignores it and goes on to wherever the next bit of unflagged bright green
text is.
If I put the cursor between two bits of unflagged brightgreen text in
a cell and step through the code then rgeTarget consists of the range
of text between the IP and the end of the cell. In your last version
rgeTarget consist of entire cell range. Hence it "finds" the text
before the cursor.

Again, as I wrote above, I did not observe this, except when the previous
bright green text in the same cell in unflagged. (The macro does reset the
range to the entire cell, but if some of the text before the IP is already
flagged, it does not matter as it ignores it.)
To fix this I set the start range of oRng1 to the end range of oRng2
in the DO statement:

So, in my mind, this is not necessary.
But if you feel you really need this, I would suggest that you place this
in the function (probably inside the "IF range in table" bit), where all
range manipulation should be handled (in order to avoid conflicts).
Do While Not boolSearchResult

Set oRng2 = Selection.Range

oRng1.Start = oRng2.End

As for the If Not .Found Statement, without it if the IP is in a
table cell that contains no more hightlighted text and there is no
more subsequent highlighted text in the document a continuous loop
occurs.

I did not observe this behaviour. I used the same document I was referring
to above. I removed all highlighting in the table and in the text below the
table in the document. Wherever I placed the IP (Before, after or inside the
table) I still got my "Text not found" message.
So with all that said, this is what I have left:

There remains at least one issue that I haven't bothered to try to
resolve. If the IP is in a table with no more text to find and there
is no more text to find in subsequent text, the cursor rests at the
end of the Table and the msgbox doesn't pop. The users will have to
fire the macro again. Seems silly to kill brain cells over ;-)

My version does not exhibit this behaviour.

I have not observed any of the behaviours you mentioned with the latest
version.
So, how did you do it? How did you manage to get these behaviours and I
didn't? If you observe them again, send me the test document you used. I am
probably missing something really obvious!

Unless all this is related to the assumption I mentioned above. If my
assumption was wrong, then the only problem my version still displays is the
case of two bits of bright green text in the same cell, in which cases,
after editing his text, the user has to place the cursor in the next cell,
not just merely at the end of the said cell (which should not be a problem,
unless he is working with cells that span full pages...). I still did not
observe any of the other behaviours.

At least, I did practice coding for cells and increased my understanding of
cell manipulation with VBA. Thanks!

--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
G

Greg Maxey

JGM,

Yes I see that your method works exactly as you describe it does. I don't
know why I was seeing the continous loop issue last night, but I am not
seeing it today.

The difference between our approaches it that I did not assume that the user
would edit and flag the first bit of text. Actually the only reason I am
still interested in this is for a general tool to step though a document
looking for highlighted text of a certain color, the ^ condition is just
left over from the original discussion.

Thanks for the dialog. Like you I learned a bit about manipulating ranges
in cells.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top