Subroutines and Functions


Subroutines group lines of code into meaningful pieces of work. A function is a subroutine that returns a value. The use of subroutines and functions facilitates testing, code reuse, and readability. This in turn reduces errors.

The keyword Sub defines the beginning of a subroutine, and End Sub defines the end of a subroutine.

 Sub FirstSub   Print "Running FirstSub" End Sub 

To use a subroutine, place the name of the subroutine that you want to call on a line. The name can optionally be preceded by the keyword Call.

 Sub Main   Call FirstSub ' Call Sub FirstSub   FirstSub      ' Call Sub FirstSub again End Sub 

Subroutine and function names must be unique in a module. They are subject to the same naming conventions as variables , including the use of spaces in their names .

 Sub One   [name with space] End Sub Sub [name with space]   Print "I am here" End Sub 
Compatibility 

Visual Basic allows a subroutine to be preceded by optional keywords such as Public or Private. In OOo Basic all subroutines and functions are public. Currently, OOo Basic does not allow you to explicitly specify the scope of a routine as Public or Private, but this is scheduled to be supported in OOo 2.0.

The keyword Function is used to declare a function which, like a variable, can define the type it returns. If the type is not declared, the return type defaults to Variant. You can assign the return value at any point and as many times as you want before the function ends. The last value assigned is returned.

 Sub test   Print "The function returns " & TestFunc End Sub Function TestFunc As String   TestFunc = "hello" End Function 

Arguments

A variable that is passed to a routine is called an argument. Arguments must be declared. The same rules for declaring variable types apply to declaring argument types.

A routine name can optionally be followed by parentheses, both when it is defined and when it is called. A routine that accepts arguments can optionally enclose the argument list in parentheses. The argument list follows the routine name on the same line. Blank space is allowed between the name of the routine and the argument list. See Listing 25 .

Listing 25: ExampleParamTest1 is found in the SubAndFunction module in this chapter's source code files as SC02.sxw.
start example
 Sub ExampleParamTestl()   Call ParamTestl(2, "Two")   Call ParamTestl 1, "One" End Sub Sub ParamTestl(i As Integer, s$)   Print "Integer = " & i & " String = " & s$ End Sub 
end example
 

Pass by Reference or by Value

By default, arguments are passed by reference rather than by value. In other words, when the called subroutine modifies an argument, the caller sees the change. You can override this behavior by using the ByVal keyword. This causes a copy of the argument (rather than a reference to the argument) to be sent (see Listing 26 and Figure 6 ).

click to expand
Figure 6: Passing by reference allows changes to be passed back to the caller.
Listing 26: ExampleParamValAndRef is found in the SubAndFunction module in this chapter's source code files as SC02.sxw.
start example
 Sub ExampleParamValAndRef()   Dim i1%, i2%   i1 = 1 : i2 = 1   ParamValAndRef(i1, i2)   MsgBox "Argument passed by reference was 1 and is now " & il & CHR$(10) &_          "Argument passed by value was 1 and is still " & i2 & CHR$(10) End Sub Sub ParamValAndRef(iRef%, ByVal iVal)   iRef = iRef + 1  ' This will affect the caller   iVal = iVal - 1  ' This will not affect the caller End Sub 
end example
 
Warning 

Constants passed as arguments by reference cause unexpected behavior if their value is modified in the called routine. The value may arbitrarily change back. For example, I had a subroutine that was supposed to decrement an Integer argument in a loop until it was zero; the argument never became zero.

Compatibility 

Visual Basic supports the optional keyword ByRef. This keyword is not supported by OOo Basic. Because passing by reference is the default behavior, the ByRef keyword was considered redundant.

Optional Arguments

You can declare arguments as optional by preceding them with the keyword Optional. All of the arguments following an optional argument must also be optional. Use the IsMissing function to determine if an optional argument is missing. See Listing 27 .

Listing 27: ExampleArgOptional is found in the SubAndFunction module in this chapter's source code files as SC02.sxw.
start example
 REM Make test calls with optional arguments. REM Calls with Integer and Variant arguments should yield the same result. REM Unfortunately, they do not. Sub ExampleArgOptional()   Dim s$   s = "Variant Arguments () => "     & TestOpt()      & CHR$(10) &_       "Integer Arguments () => "     & TestOptI()     & CHR$(10) &_       "---------------------------------------------" & CHR$(10) &_       "Variant Arguments () => "    & TestOpt()     & CHR$(10) &_       "Integer Arguments () => "    & TestOptI()    & CHR$(10) &_       "---------------------------------------------" & CHR$(10) &_       "Variant Arguments (1) => "    & TestOpt(1)     & CHR$(10) &_       "Integer Arguments (1) => "    & TestOptI(1)    & CHR$(10) &_       "---------------------------------------------" & CHR$(10) &_       "Variant Arguments (,2) => "   & TestOpt(,2)    & CHR$(10) &_       "Integer Arguments (,2) => "   & TestOptI(,2)   & CHR$(10) &_       "---------------------------------------------" & CHR$(10) &_       "Variant Arguments (1,2) => "  & TestOpt(1,2)   & CHR$(10) &_       "Integer Arguments (1,2) => "  & TestOptI(1,2)  & CHR$(10) &_       "---------------------------------------------" & CHR$(10) &_       "Variant Arguments (1,,3) => " & TestOpt(13)   & CHR$(10) &_       "Integer Arguments (1,,3) => " & TestOptI(13)  & CHR$(10)   MsgBox s, 0, "Optional Arguments of Type Variant or Integer" End Sub REM Return a string that contains each argument. If the argument REM is missing, then an M is used in its place. Function TestOpt(Optional vl, Optional v2, Optional v3) As String   TestOpt = "" & IIF(IsMissing(vl), "M", Str(vl)) &_                  IIF(IsMissing(v2), "M", Str(v2)) &_                  IIF(IsMissing(v3), "M", Str(v3)) End Function REM Return a string that contains each argument. If the argument REM is missing, then an M is used in its place. Function TestOptI(Optional il%, Optional i2%, Optional i3%) As String   TestOptI = "" & IIF(IsMissing(il), "M", Str(il)) &_                   IIF(IsMissing(i2), "M", Str(i2)) &_                   IIF(IsMissing(i3), "M", Str(i3)) End Function 
end example
 
Compatibility 

Although Visual Basic .NET no longer supports the IsMissing function, it provides another mechanism for specifying default values to be automatically assigned to missing parameters.

You can omit any optional arguments. Listing 27 demonstrates two functions that accept optional arguments. The functions are the same except for the argument types. Each function returns a string containing the argument values concatenated together. Missing arguments are represented by the letter "M" in the string. Although the return values from TestOpt and TestOpt1 should be the same for the same argument lists, they are not (see Figure 7 ). This is a bug.

click to expand
Figure 7: In rare cases, non-Variant optional arguments fail.
Bug 

The IsMissing function returns incorrect results for variables that are not of type Variant when the missing argument is followed by a comma.

Compatibility 

VBA supports default values. OOo Basic does not, but is scheduled to support them in version 2.0.

In OOo 1.1.0, default values are not supported. Default values are scheduled to be supported by version 2.0. This allows a default value to be specified if an optional argument is missing. You must use the keywords "Option Compatible" for default values to work.

 Option Compatible Sub DefaultExample(Optional n as Integer=100)   REM If IsMissing(n) Then n = 100 'I will not have to do this anymore!   Print n End Sub 

Recursive Routines

A recursive routine calls itself. As of OpenOffice.org 1.1, recursion is supported. Consider, for example, calculating the mathematical function Factorial for positive integers. The usual definition is recursive (see Listing 28 ).

Listing 28: DoFactorial is found in the SubAndFunction module in this chapter's source code files as SC02.sxw.
start example
 Sub DoFactorial   Print "Recursive Factorial = " & RecursiveFactorial(4)   Print "Iterative Factorial = " & IterativeFactorial(4) End Sub Function IterativeFactorial(ByVal n As Long) As Long   Dim answer As Long   answer = 1   Do While n > 1     answer = answer * n     n = n - 1   Loop   IterativeFactorial = answer End Function ' This finally works in version 1.1 Function RecursiveFactorial(ByVal n As Long) As Long   RecursiveFactorial = 1   If n > 1 Then RecursiveFactorial = n * RecursiveFactorial(n-1) End Function 
end example
 

Computers use a data structure called a stack. At home, I have a stack of books that I want to read. When I receive a new book, I place it on top of the stack. When I have time to read, I take the top book from the stack. This is similar to the data structure that a computer uses: a section of memory in a computer for temporary storage in which the last item stored is the first retrieved. Stacks are usually used when a computer calls a routine and passes arguments. A typical procedure follows:

  1. Push the current run location onto the stack.

  2. Push each argument onto the stack.

  3. Call the desired function or subroutine.

  4. The called routine uses the arguments from the stack.

  5. The called routine frequently uses the stack to store its own variables.

  6. The called routine removes the arguments from the stack.

  7. The called routine removes and saves the caller's location from the stack.

  8. If the called routine is a function, the return value is placed on the stack.

  9. The called routine returns to the caller.

  10. If the called routine is a function, the return value is taken from the stack.

Although various optimizations are used, there is always some overhead associated with calling subroutines and functions. There is overhead in running time and in the memory required. The recursive version of Factorial continually calls itself. While calculating the factorial of four, there is one point at which the stack contains information for calls for 4, 3, 2, and 1. For some functions-the Fibonacci series, for example-this call behavior may be prohibitive, and a non-recursive algorithm should be used instead.




OpenOffice.org Macros Explained
OpenOffice.org Macros Explained
ISBN: 1930919514
EAN: 2147483647
Year: 2004
Pages: 203

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net