FORM

Basic form

FORM form [TABLES ...] [USING ...] [CHANGING ...].

Extras:


1. ... TABLES   itab1             ... itabn

2. ... USING    [VALUE(p1)|p1]    ... [VALUE(pn)|pn]

3. ... CHANGING [VALUE(p1)|p1]    ... [VALUE(pn)|pn]

4. ... RAISING cx1 ... cxn

Effect

Defines a subroutine called by PERFORM

You can assign a type to the parameters of the subroutine. For details about types of formal parameters, see specifying forms.

Example

PERFORM WELCOME.

FORM WELCOME.
  WRITE / 'Hello world'.
ENDFORM.

The subroutine WELCOME called by the PERFORM statement outputs 'Hello world'.

Notes

  1. Subroutines defined by FORM can have parameters and local fields. These parameters and local fields shadow global fields. Their visibility begins at their declaration, and ends at the ENDFORM statement.
  2. Any local fields you declare with DATA after a FORM statement are recreated and initialized for each PERFORM call. When the call has finished, the memory for local fields is released again.
  3. You can defined global fields that are only visible within the FORM using the STATICS statement.
  4. You can define global data that you want to use locally within a subroutine using the LOCAL statement after the FORM statement. The values for this data are saved when you enter the subroutine, and released from the stack when you leave it.
  5. FORM statements are not allowed within FORM ... ENDFORM structures (i.e. no nested definitions).
  6. Nested and recursive calls are possible.
  7. The parameters must always be specified in the order TABLES, USING, CHANGING, and RAISING.


Addition 1

... TABLES itab1 ... itabn

Effect

Instead of the TABLES addition, you should use the USING or CHANGING addition wherever possible. You can only use tables with table type STANDARD in the TABLES addition. The internal tables you specify are always passed to the FORM along with their header line. If you pass a table without header line as a TABLES parameter, the system automatically generates a header line for it. This is only valid within the FORM . You should not use any global commands (such as HIDE) on the header line. For details about specifying the type of a TABLES parameter, see specifying types. TABLES parameters are always passed by reference.

Example

TYPES: BEGIN OF T_X.
       INCLUDE STRUCTURE SFLIGHT.
TYPES: ADDITION(8) TYPE C,
       END OF T_X.
...
DATA:  X TYPE STANDARD TABLE OF T_X WITH NON-UNIQUE
       DEFAULT KEY INITIAL SIZE 0.
FORM U TABLES X STRUCTURE SFLIGHT.
...
PERFORM U TABLES X.
...
FORM U TABLES X STRUCTURE SFLIGHT.
  WRITE: X-FLDATE.
ENDFORM.

Addition 2

... USING [VALUE(p1)|p1] ... [VALUE(pn)|pn]

Effect

Defines formal parameters p1,...pn, which are replaced by actual parameters when the subroutine is called.
You can assign a type to the formal parameters p1, ..., pn (see specifying types). You can also specify the method with which they are passed.

Note

Passing methods:

  1. USING ... p ...
    The parameters are passed by reference. The field passed can be changed within the subroutine. The changes are kept beyond the subroutine.
  2. USING ... VALUE(p) ...
    The VALUE(...) addition passes the parameter by copying the field contents to a corresponding local field. VALUE parameters behave in the same way as local fields.

Example

TYPES: BEGIN OF FLIGHT_STRUC,
         FLCARRID LIKE SFLIGHT-CARRID,
         PRICE    LIKE  SFLIGHT-FLDATE,
       END   OF FLIGHT_STRUC.

DATA: MY_FLIGHT TYPE TABLE OF FLIGHT_STRUC,
      IBOOK1    TYPE TABLE OF SBOOK,
      IBOOK2    LIKE TABLE OF IBOOK1,
      STRUC     TYPE SBOOK.

PERFORM DISPLAY USING MY_FLIGHT IBOOK1 IBOOK2 STRUC.

FORM DISPLAY USING  P_ITAB  LIKE      MY_FLIGHT[]
                    P_BOOK1 LIKE      IBOOK1[]
                    P_BOOK2 LIKE      IBOOK2[]
                    P_STRU  LIKE      STRUC.

  DATA: L_FLIGHT  LIKE LINE OF P_ITAB,
        L_CARRID  LIKE L_FLIGHT-FLCARRID.
  ...
  WRITE: / P_STRU-CARRID, P_STRU-CONNID.
  ...
  LOOP AT P_ITAB INTO L_FLIGHT WHERE FLCARRID = L_CARRID.
    ...
  ENDLOOP.
ENDFORM.

Addition 3

... CHANGING [VALUE(p1) |(p1)] ... [VALUE(pn) |(pn)]

Effect

The parameters after CHANGING can accept the same specifications as those after USING.
To link the VALUE specification with the change of a parameter value, you can use the addition CHANGING ... . Then, all the formal parameters specified by VALUE(...) are transported back to the actual parameters at the end of the subroutine (i.e. after ENDFORM). If the subroutine is terminated by a dialog message, none of the parameters referenced by CHANGING VALUE ... changes.
Otherwise, the effect of USING and CHANGING is identical.

Example

DATA: NUMBER_1 TYPE I VALUE 1,
      NUMBER_2 TYPE I VALUE 2,
      TEXT_1(10)      VALUE 'one',
      TEXT_2(10)      VALUE 'two'.

PERFORM CONFUSE USING NUMBER_1
                      NUMBER_2
                      TEXT_1
                      NUMBER_1
                      TEXT_2.

FORM CONFUSE USING PAR_NUMBER_1 TYPE I
                   PAR_NUMBER_2 TYPE I
                   PAR_TEXT_1   TYPE C
                   VALUE(PAR_V_NUMBER_1) TYPE I
                   VALUE(PAR_V_TEXT_2) TYPE C.
  ADD 3 TO PAR_V_NUMBER_1.
  ADD 4 TO PAR_NUMBER_1.
  ADD NUMBER_1 TO PAR_NUMBER_2.
  TEXT_2 = 'three'.
  PAR_TEXT_1 = PAR_V_TEXT_2.
  PAR_V_TEXT_2 = 'four'.
ENDFORM.

Field contents after the PERFORM call:

    NUMBER_1 = 5
    NUMBER_2 = 7
    TEXT_1   = 'two'
    TEXT_2   = 'three'


Addition 4

... RAISING cx1 ... cxn

Effect

The addition you can use for the definition of METHODS, FORM and FUNCTION informs the calling program which class-based exceptions can occur.

After RAISING, you therefore list the exception classes whose exceptions may occur and which cannot be caught locally within the procedure. You may only specify classes of the categories CX_STATIC_CHECK and CX_DYNAMIC_CHECK. It is possible to specify superclasses to declare groups of exceptions in a simple manner. Since the order of the exceptions is important to the CATCH clause, you must specify the exception classes according to their inheritance hierarchy even if you declare them in ascending order.

If the interface is violated at runtime for exceptions of the categories CX_STATIC_CHECK and CX_DYNAMIC_CHECK - that is, an exception of this type leaves a procedure and the exception was not defined in the RAISING clause - the system triggers an exception of the class CX_SY_NO_HANDLER and stores a reference to the original exception in the attribute PREVIOUS. (Any handler for such an exception then does not catch the original exception but instead a programming error in the procedure called.)

The addition may only be used for the definition of METHODS and FUNCTIONS if the addition EXCEPTIONS (for exceptions that are not class-based) is not used simultaneously. Also, using the RAISING addition within the procedure defined that way means the following restrictions:

Note

In subroutines, you are recommended to use the following procedure:

  1. Pass input parameters as USING parameters and output parameters as CHANGING parameters. If in doubt, pass the parameter by VALUE. You should be particularly careful with passed SY fields. For performance reasons, data objects which contain tables should not be passed by VALUE if at all possible.
  2. You can protect TABLES parameters whose header lines must remain unchanged with LOCAL.
  3. STATICS allows you to create global fields with a local visibility area. In the case of local fields which are initialized on each call, you can replace DATA by STATICS. With frequently called FORM routines, this can lead to a noticeable improvement in performance.
  4. To avoid shadowing problems with parameters, you are recommended to keep to the naming convention for fields in subroutines. You should, for instance, always start FORM parameters with the prefix 'P_' and local fields with the prefix 'L_'.

Additional help

Defining Subroutines