OML for the complete beginner, #7

Loops

A loop is exactly that--when the computer reaches the "end" of the loop, it loops back around to the beginning of the loop and starts over. Some loops control how many times the computer will loop (some of these can even change how many times they loop, as needed), and some have no control whatsoever.

The most basic loop involves the Goto statement. This statement does exactly that--tells the computer to go to some other area of the program and execute the commands it finds there as if they actually immediately followed the Goto statement.

(Warning: Do not try the following mini-macro without taking proper precautions! Unless you use the green arrow on the Macro Editor toolbar to run this macro (in which case you can stop it at any time by using the stop button on the macro editor toolbar), it will cause Passport for Windows to crash!)

  sub main
    x=1
    Start:
      Text$="Hello, world "+Str$(x)
      CurrentSession.PutText Text$, 1, 1
      x=x+1
      Goto Start
  end sub

This macro will theoretically run forever--in practice, it will run until the program locks up or the user halts the macro--endlessly finding the home position and putting the text "Hello, world" there and a number representing the number of times the loop has executed.

Labels are usually a word or combination of words written without spaces or with underscores instead of spaces, that are the first or only thing found on a line and end with a colon. When referred to by other commands, such as Goto, the colon is left off. Labels by themselves can also be used to identify various parts of a program if you don't need to use long and involved commented explanations; this is one way to tell at a glance what a certain program block does.

This macro provides us with the most basic example of a loop--in this case, an infinite loop. When the computer reaches the Goto statement, it loops back around to the line marked "Start" and proceeds to execute each of the commands found there. Since there is no way to determine when to stop looping, it will execute an infinite number of times. However, infinite loops are extremely bad things, to be avoided at all costs outside of the classroom. It's not too difficult for an infinite loop to eat up so much of the computing resources available that Passport crashes and has to be closed down and restarted! (If there's one thing Passport and Microsoft Windows both loathe, it is infinite loops.)

If you need a loop to execute a series of commands a specific number of times, one method is to use a For...Next loop.

  sub main
  For i = 1 to 10
    CurrentSession.PutText "Hi", i, 1
  Next i
  end sub

This program puts the word "Hi" at the beginning of the first ten lines of the screen. Note that it is optional to use the i with the Next statement, but it can help to keep loops straight when you combine them:

  sub main
  x=9
  For i = 1 to x Step 2
    For j = 1 to 3
      CurrentSession.PutText, "N", i, j
    Next j
  Next i
  end sub

This program puts the character "N" in the first three positions of every odd-numbered row up to and including row 9. The Step part of the command tells it, in this case, to count from 1 to 9 by two's.

A For...Next loop is ok for some things, but it is only of any real use when you know in advance exactly how many times the loop must execute. It also can have serious problems if you use variables, such as the x in the above example, for anything but counting. If you redefine the counting variables with statements inside the loop, it is extremely easy to end up with a macro that simply doesn't work or, more likely, an infinite loop. As you can see, while it does have its uses, the For...Next loop isn't really all that versatile, especially when you consider its cousin, the Do...Loop statements.

  sub main
  x = 0
  Do Until x = 10
    x = x + 1
  Loop

  y = 0
  Do
    y = y + 1
  Loop Until y = 10

  z = 0
  Do While z < 10
    z = z + 1
  Loop
  end sub

These three loops seem to be functionally the same, but upon closer examination, some important differences come to light. The first one hits the Do statement, sees that x does not equal 10, and starts executing the commands inside the loop until it does equal 10. It will execute 10 times, then skip from the Do statement to the first statement after the loop. The second goes through the entire loop once before testing whether or not to loop, at which point y will already equal 1; therefore it will only run 9 times. The third is an alternate wording that works better in conjunction with certain other commands rather than a simple inequality, such as Do While CS.Find(a$, 1, 1), which will loop for as long as a$ appears on the screen. Like all loops, Do...Loops have the unfortunate tendency to easily result in infinite loops, but these loops also allow a surefire method of preventing this from happening. If you think an infinite loop might be a possibility, it is best to add in an independent counting variable that does nothing but tally how many times the loop has executed.

    sub main
      x=0 : y=0
      Do Until x=11
        If y>=20 Then
          Exit Do
        End If
        x=x+2
        y=y+1
      Loop
      MsgBox "I am out of the loop."
    end sub

As you can see, this loop has a problem: since it is counting from zero by twos, it will successively equal 2, 4, 6, and so forth, and will never equal eleven. If that were all there was to the loop, the loop would go on and on, endlessly waiting for an eleven to turn up. However, we have added another variable, a "control group", as it were, to prevent that from happening. The loop statements are only concerned with the value of x; however, each time the program loops, y also increases by one. When y reaches 20--that is, when the program has looped 20 times--then an Exit Do statement is executed, which automatically sends the program on to the command immediately following the Loop statement. In this case, a message box pops up showing that the program made it beyond the loop.

Next time, program flow control...


Return to Lesson #6.
Return to Main page.