Skipping in a loop

B

Bear

Does anyone know a way to loop through all instances in a collection,
but *skip* doing something to unqualified members?

I know I could go

For Each objPara in Selection.Paragraphs
If [Disqualifier] = False Then
Do the stuff for qualified members
Endif
Next objPara

But I'm looking for something more like

For Each objPara in Selection.Paragraphs
If [Disqualifier] = True Then
GoTo Skip
Endif
Do the stuff for qualified members
Skip:
Next objPara

Bear
 
N

NZ VBA Developer

Bear,

One of the tools I use regularly can't work with individual table rows
because Word doesn't recognise/advertise the selection of a row or rows
within a table as having something selected. Consequently, I have to break
the table up into several smaller tables and select the line before the table
as well before the Word "tells" the tool that something is selected. Of
course the end result is that the final document ends up with a bunch small
tables in it rather than a one or more larger tables. To get around this I
apply a specific style to the line before the "split" tables (usually 1pt and
hidden - just to be safe) and then use a bit of VBA to go through the
document and delete out all of the paragraphs with that particular style. The
tables then re-concatenate and all is right with the world.

The code I use looks like this:

Sub ConcatenateTables
Dim myPara as Paragraph
For each myPara in ActiveDocument.Paragraphs
If myPara.Style="1pt Para" Then myPara.Range.Delete
Next myPara
End Sub

This is very similar to your first example below. In fact it would be almost
exactly the same if I changed "ActiveDocument.Paragraphs" to
"Selection.Paragraphs" and fiddled a bit with the condition evaluated by the
If statement; e.g. "If Not [Condition] Then..." This works just fine (altho
it might be a little slow if my document contains a lot of paragraphs) and
I'll undoubtedly continue to use it.

Is there a specific reason why you want to use the Goto? I can't see how it
would make the code any faster since the stuff inside the If statement
doesn't execute if the related conditions aren't satisfied anyway...
 
H

Helmut Weber

Hi Bear,

there must be more to it than your posting reveals.

For Each objPara in Selection.Paragraphs
If qualifier Then
Do the stuff for qualified members
Endif
Next objPara

For Each objPara in Selection.Paragraphs ' ?
If not qualifier Then
' Do nothing
else
Do the stuff for qualified members
Endif
Next objPara '?

--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 
B

Bear

There's no particular application. (I happen to be working on automating
ListNum fields.) But imagine wanting to work through a collection of
paragraphs, and subjecting each paragraph to three or four tests, any of
which might render the paragraph ineligible for processing. It would be nice
to say:

For Each objPara in Selection.Paragraphs
If objPara.Range.Font.Hidden = True Then Next
If objPara.Range.Fields = 0 Then Next
If objPara.Type <> wdBogonPara Then Next
objPara.Property = Value
etc., etc.
objPara.Method
Next objPara

rather than having all those tests indent and indent.

Another way might be to set the value of a flag.

For Each objPara in Selection.Paragraphs
flgValid = True
If objPara.Range.Font.Hidden = True Then flgValid = False
If objPara.Range.Fields = 0 Then flgValid = False
If objPara.Type <> wdBogonPara Then flgValid = False
If flgValid = True Then
objPara.Property = Value
etc., etc.
objPara.Method
End If
Next objPara
 
S

Shauna Kelly

Hi Bear

If this were mine, I'd use a separate function to perform the test, eg:

Sub One
For each objPara in selection.paragraphs
if mPassesMyText (oPara:=objPara) then
'do stuff
endif
next objPara
End Sub

Function mPassesMyTest (oPara as word.paragraph) as boolean

if oPara.range.font.size = 12 and _
oPara.etc etc etc then
mPassesMyTest = True
end if

End Function

In real life you might have several layers deep of the testing process.

By the way, if issues like this interest you, I would recommend Code
Complete (2nd ed.) by Steve McConnell (http://www.cc2e.com/).

Hope this helps.

Shauna Kelly. Microsoft MVP.
http://www.shaunakelly.com/word
 
B

Bear

Shauna:

That's something like what I ended up doing. But I was trying to pass a
range to a function, and couldn't make it work. In the end I defined a
module-level range object and had the subroutine work on that.

Can one pass a range to a function or subroutine in other ways?

Bear
--
Windows XP, Word 2000


Shauna Kelly said:
Hi Bear

If this were mine, I'd use a separate function to perform the test, eg:

Sub One
For each objPara in selection.paragraphs
if mPassesMyText (oPara:=objPara) then
'do stuff
endif
next objPara
End Sub

Function mPassesMyTest (oPara as word.paragraph) as boolean

if oPara.range.font.size = 12 and _
oPara.etc etc etc then
mPassesMyTest = True
end if

End Function

In real life you might have several layers deep of the testing process.

By the way, if issues like this interest you, I would recommend Code
Complete (2nd ed.) by Steve McConnell (http://www.cc2e.com/).

Hope this helps.

Shauna Kelly. Microsoft MVP.
http://www.shaunakelly.com/word
 
S

Shauna Kelly

Hi Bear

Sure. Here's a little example which shows using a range as a parameter to a
Sub and a Function.

Option Explicit

Sub StartHere()

Dim rngSelection As Word.Range
Dim sStyleName As String

'Get a reference to the selected range
'(in real life you need error checking here in
'case the user has selected, eg, an image)
Set rngSelection = Selection.Range

'Send our selection off to the mGetRangeStyle function
'to be processed, and get back the name of the style
sStyleName = mGetFirstParaStyle(oRange:=rngSelection)

'Use the return value to tell the user what's happening
MsgBox "The first paragraph in the selection is in style " & sStyleName

'Send our range off to the mMakeRangePink sub that
'will format the font of our range as pink
mMakeRangePink oRange:=rngSelection

End Sub

Private Function mGetFirstParaStyle(ByRef oRange As Word.Range) As String

Dim sRetval As String

'Make sure we have a range to play with..
If Not oRange Is Nothing Then

'Get the name of the style of the first
'paragraph of our range
'(in real life you need error checking here in case
'we're in a protected document or something'
sRetval = oRange.Paragraphs(1).Style

End If

'Set the return value
mGetFirstParaStyle = sRetval

End Function

Private Sub mMakeRangePink(ByRef oRange As Word.Range)

'Make sure we have a range to play with
If Not oRange Is Nothing Then

'make it pink
oRange.Font.Color = wdColorRose

End If

'This is a Sub so it doesn't have a return value
'But it has actually *changed* the oRange.

End Sub


I explicitly put in "ByRef" in the arguments of the Sub and Function to
remind us that an object is, by default, passed "By reference". That means
that the lower-level routine receives a reference to the object, and
anything you do to the object (eg, make it pink) actually changes the
object.


Hope this helps.

Shauna Kelly. Microsoft MVP.
http://www.shaunakelly.com/word


Bear said:
Shauna:

That's something like what I ended up doing. But I was trying to pass a
range to a function, and couldn't make it work. In the end I defined a
module-level range object and had the subroutine work on that.

Can one pass a range to a function or subroutine in other ways?

Bear
 
B

Bear

Many thanks to all who helped me along with this project.

After many twists and turns, I think I found the structure best suited
to my application, and that's the ElseIf of the If - Then - Else
statement. I used it like this:


For Each objPara In rngWork.Paragraphs

Set rngPara = objPara.Range
Set rngCollapse = rngPara
rngCollapse.Collapse

If rngPara.Font.Hidden = True Then
' No action for hidden paras
ElseIf rngCollapse.Information(wdAtEndOfRowMarker) = True Then
' No action for end of row marker
ElseIf rngPara.text = Chr(13) & Chr(7) Then
' No action for empty cells
Else
Select Case strAction
Case "Number"
etc.
Case Else
End Select
End If

Next objPara


As you can see, the each objPara runs a "gauntlet of tests" in the If
and ElseIf statements. If it fails any test, it isn't acted on, but the
Select Case structure (that does the work on valid paras) is skipped
over and the next objPara is selected for testing.

Bear
 

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