VBA - help with For...Next loops

T

Tedsec

Okay, I have a For..Next loop where I want to add a condition in the
middle. If my item meets a certain criteria, I want to skip through
the loop to the next item. Here is my code right now:


For x = 14 To 34

If headings(x) = "Standard 1" Or "Standard 2" Or "Standard 3" Or
"Standard 4" Or "Standard 5" Or "Standard 6" Or "Standard 7" Or
"Standard 8" Or "Standard 9" Or "Standard10" Then
Next x
End If

***rest of code here***

Next x

In other words, if headings(x) equals any of those strings, I don't
want to perform any logic on it, I want to skip to the next heading.
However, VBA doesn't like my syntax. It says "Block If without End
If". Is there a way to program in the logic I want to have?

Thx in advance.

Ted
 
E

Elliott Roper

Tedsec said:
Okay, I have a For..Next loop where I want to add a condition in the
middle. If my item meets a certain criteria, I want to skip through
the loop to the next item. Here is my code right now:


For x = 14 To 34

If headings(x) = "Standard 1" Or "Standard 2" Or "Standard 3" Or
"Standard 4" Or "Standard 5" Or "Standard 6" Or "Standard 7" Or
"Standard 8" Or "Standard 9" Or "Standard10" Then
Next x
End If

***rest of code here***

Next x

In other words, if headings(x) equals any of those strings, I don't
want to perform any logic on it, I want to skip to the next heading.
However, VBA doesn't like my syntax. It says "Block If without End
If". Is there a way to program in the logic I want to have?

Thx in advance.

Ted
I don't speak VBA, but all you have to do to untangle that is turn the
logic upside down

For stuff
if *not* (this or that or the other)
rest of code
end if
next lump of stuff

see how the if - end if is now nested neatly inside the for - next.

Your text description already had the answer didn't it?

If VBA won't let you build such a conditional expression, you would get
the same with
for stuff
if not this and not that and not the other damn thing then
yadda
end if
next lump of stuff

quite good fun really.
 
J

JE McGimpsey

Tedsec said:
In other words, if headings(x) equals any of those strings, I don't
want to perform any logic on it, I want to skip to the next heading.
However, VBA doesn't like my syntax. It says "Block If without End
If". Is there a way to program in the logic I want to have?

Control structures must nest within other control structures. Your first
"Next" is inside the If...End If structure and is therefore invalid (in
any case, each For can have exactly one Next).

Try something like

For x = 14 To 34
If Not (headings(x) Like "Standard [1-9]" Or_
headings(x) = "Standard 10") Then
'***rest of code here***
End If
Next x
 
T

Tedsec

Thanks for the help...how abou this:

As I was implementing your suggestions, I thought about the
select...case statement. This is what I wrote, and it works fine:

Select Case headings(x)
Case "Standard 1", "Standard 2", "Standard 3", "Standard 4",
"Standard 5", "Standard 6", "Standard 7", "Standard 8", "Standard 9",
"Standard 10"
'do nothing

Case Else
***logic code here***

End Select

Will this be faster/slower than your suggestion? I never hear much
about Case statements...are they generally acceptable, or looked down
upon?
 
J

JE McGimpsey

Tedsec said:
Will this be faster/slower than your suggestion? I never hear much
about Case statements...are they generally acceptable, or looked down
upon?

The technique is certainly valid. I would expect it to be slower than
the one I suggested, but it would probably not be noticeable.

Control structures have better and worse uses. Often there isn't a clear
preference. In general, my philosophy for non-commercial work is "if it
works, it's right".

If you have an extra $50, MVPs Stephen Bullen, Rob Bovey, and John Green
have just published a fantastic new book "Professional Excel
Development" from Addison Wesley. It's geared toward WinXL developers,
but it has some great stuff for cross-platform developers, too.

There's some good stuff on efficiency at Charles Williams' Decision
Models site:

http://www.decisionmodels.com/optspeed.htm
 
J

John McGhie [MVP - Word and Word Mac]

Hi Ted:

Select Case statements are very much encouraged from the point of view of
readability and thus maintainability of your code. Most VBA coders use tem
whenever they can.

I believe that John (the other one) is correct when he says that for this
particular application, Select Case is likely to be slower than the method
he suggested.

However, in general, a carefully designed Select Case can be very much
faster. That's because the system needs to evaluate the left side of the
condition only once. The rest of the Select Case is compiled into a series
of single-shot IF statements. These evaluate very quickly and are thus very
efficient. A benefit of Select Case is that evaluation stops with the first
TRUE return, so by designing your Cases in order from most likely to least
likely, you can get a substantial efficiency improvement.

If you are dealing with very long documents (> 500 pages) you will get a
handy speed improvement by creating your own collection. You could try
something like this:

Sub AddCollection()

Dim notHeadings As New Collection
Dim i As Long
Dim numParagraphs As Long
Dim aParagraph As Paragraph

Application.ScreenUpdating = False
numParagraphs = ActiveDocument.Paragraphs.Count

With ActiveDocument.Paragraphs
For i = 1 To numParagraphs
If Not .Item(i).Style.NameLocal Like "Standard" Then
notHeadings.Add .Item(i)
End If
Next ' i
End With

numParagraphs = notHeadings.Count
With notHeadings
For i = 1 To numParagraphs
With .Item(i)

' ... Do stuff
End With
Next ' i
End With

Set notHeadings = Nothing

End Sub


Please note: I have compiled that, but not tested it. This example has
several VBA go-faster techniques in it:

a) by adding all the paragraphs you want to process to a collection, you
get a very good speed increase. The test is a single IF statement that
operates on a key field in a collection Word already maintains, so it
happens at binary speed.

b) By evaluating ActiveDocument.Paragraphs.Count once only and storing the
result in a variable, you improve the speed two orders of magnitude in a
long document, because Word does not have to enumerate the collection on
each iteration through the loop.

c) The Next ' i construct is interesting. The Next terminator of a
For...Next loop causes an imperative branch back to the closest For
statement. That's all it does: we do not need to know the value of i in
order to get there. But if you include i in the statement, VBA will
evaluate i twice, once at the beginning and once at the end of the loop.
Adding the apostrophe turns "i" into a comment. You can see where the
branch is going, Word already knows, and it then evaluates i only once per
iteration, doubling the speed.

d) Dimming all of the numeric variables as long integers produces another
four times speed improvement. A Long is a full word, a native binary
integer of 32 bits. Its value can be directly evaluated in binary.
Anything else has to be byte-aligned and parsed to be evaluated.

e) Turning screen updating OFF produces another improvement in speed that
can be very substantial. Word suppresses screen updating, and thus
suppresses the pagination necessary to perform that, for the duration of the
macro.

Now, this is pretty cryptic code, and you won't see much improvement until
the document size exceeds a few hundred pages. In a short document, the
overhead of creating the collection will outweigh the benefits. If you are
running in less than 512 MB of memory, it's not a great idea to create
collections of large objects such as paragraphs, because VBA will start to
gobble memory. If it causes the system to flog the paging file things will
get very slow :)

Of course, that's why we destroy the collection when we're finished, to make
sure we get all that memory back :)

Hope this helps

--

Please reply to the newsgroup to maintain the thread. Please do not email
me unless I ask you to.

John McGhie <[email protected]>
Microsoft MVP, Word and Word for Macintosh. Consultant Technical Writer
Sydney, Australia +61 4 1209 1410
 

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